diff --git a/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt index 9b4288ad1..294d02e12 100644 --- a/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/account/components/AccountComponentsPatch.kt @@ -14,12 +14,14 @@ import app.revanced.patches.music.utils.integrations.Constants.ACCOUNT_CLASS_DES import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object AccountComponentsPatch : BaseBytecodePatch( @@ -43,8 +45,14 @@ object AccountComponentsPatch : BaseBytecodePatch( MenuEntryFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val textIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") - val viewIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val textIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } + val viewIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val textRegister = getInstruction(textIndex).registerD val viewRegister = getInstruction(viewIndex).registerD @@ -64,9 +72,14 @@ object AccountComponentsPatch : BaseBytecodePatch( AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val textColorIndex = getTargetIndexWithMethodReferenceNameOrThrow("setTextColor") - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow(textColorIndex, "setVisibility") + val textColorIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setTextColor" + } + val setVisibilityIndex = indexOfFirstInstructionOrThrow(textColorIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val textViewInstruction = getInstruction(setVisibilityIndex) @@ -98,8 +111,12 @@ object AccountComponentsPatch : BaseBytecodePatch( TermsOfServiceFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("/PrivacyTosFooter;->setVisibility(I)V") + val insertIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.name == "setVisibility" && + reference.definingClass.endsWith("/PrivacyTosFooter;") + } val visibilityRegister = getInstruction(insertIndex).registerD diff --git a/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt index 7adeadfdc..af0f94b91 100644 --- a/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/actionbar/components/ActionBarComponentsPatch.kt @@ -15,10 +15,9 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.LikeDis import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.video.information.VideoInformationPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -26,6 +25,7 @@ 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import kotlin.math.min @Suppress("unused") @@ -48,7 +48,10 @@ object ActionBarComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { // hook download button - val addViewIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val addViewIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val addViewRegister = getInstruction(addViewIndex).registerD @@ -83,10 +86,15 @@ object ActionBarComponentsPatch : BaseBytecodePatch( removeInstruction(replaceIndex) // hide action button - val hasNextIndex = getTargetIndexWithMethodReferenceNameOrThrow("hasNext") + val hasNextIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.name == "hasNext" + } val freeRegister = min(implementation!!.registerCount - parameters.size - 2, 15) - val spannedIndex = getTargetIndexWithReferenceOrThrow(")Landroid/text/Spanned;") + val spannedIndex = indexOfFirstInstructionOrThrow { + getReference()?.returnType == "Landroid/text/Spanned;" + } val spannedRegister = getInstruction(spannedIndex).registerC val spannedReference = getInstruction(spannedIndex).reference @@ -124,7 +132,8 @@ object ActionBarComponentsPatch : BaseBytecodePatch( LikeDislikeContainerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(LikeDislikeContainer) + 2 + val insertIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(LikeDislikeContainer) + 2 val insertRegister = getInstruction(insertIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt index d490534a5..9a1d8d21c 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/AdsPatch.kt @@ -22,19 +22,21 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ButtonContainer import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.FloatingLayout import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.InterstitialsContainer +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PrivacyTosFooter import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Suppress("unused") object AdsPatch : BaseBytecodePatch( @@ -87,7 +89,7 @@ object AdsPatch : BaseBytecodePatch( FloatingLayoutFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(FloatingLayout) + 2 + val targetIndex = indexOfFirstWideLiteralInstructionValueOrThrow(FloatingLayout) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -103,7 +105,8 @@ object AdsPatch : BaseBytecodePatch( NotifierShelfFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val linearLayoutIndex = getWideLiteralInstructionIndex(ButtonContainer) + 3 + val linearLayoutIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ButtonContainer) + 3 val linearLayoutRegister = getInstruction(linearLayoutIndex).registerA @@ -135,16 +138,20 @@ object AdsPatch : BaseBytecodePatch( AccountMenuFooterFingerprint.resultOrThrow().let { it.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.PrivacyTosFooter) - val walkerIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) - val viewIndex = getTargetIndexOrThrow(constIndex, Opcode.IGET_OBJECT) + indexOfFirstWideLiteralInstructionValueOrThrow(PrivacyTosFooter) + val walkerIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + val viewIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IGET_OBJECT) val viewReference = getInstruction(viewIndex).reference.toString() val walkerMethod = getWalkerMethod(context, walkerIndex) walkerMethod.apply { - val insertIndex = getTargetIndexWithReferenceOrThrow(viewReference) - val nullCheckIndex = getTargetIndexOrThrow(insertIndex - 1, Opcode.IF_NEZ) + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == viewReference + } + val nullCheckIndex = + indexOfFirstInstructionOrThrow(insertIndex - 1, Opcode.IF_NEZ) val nullCheckRegister = getInstruction(nullCheckIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt index e0ba63d86..d76a6847d 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/NotifierShelfFingerprint.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ButtonContainer import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicNotifierShelf -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object NotifierShelfFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(MusicNotifierShelf) - && methodDef.containsWideLiteralInstructionIndex(ButtonContainer) + methodDef.containsWideLiteralInstructionValue(MusicNotifierShelf) + && methodDef.containsWideLiteralInstructionValue(ButtonContainer) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt index b83d05c76..49e108d66 100644 --- a/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/ads/general/fingerprints/ShowDialogCommandFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.ads.general.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.SlidingDialogAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode internal object ShowDialogCommandFingerprint : MethodFingerprint( @@ -16,7 +16,7 @@ internal object ShowDialogCommandFingerprint : MethodFingerprint( // 6.26 and earlier has a different first parameter. // Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures. customFingerprint = custom@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(SlidingDialogAnimation)) { + if (!methodDef.containsWideLiteralInstructionValue(SlidingDialogAnimation)) { return@custom false } // 6.26 and earlier parameters are: "L", "L" diff --git a/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt index 9e67be635..eaae9f555 100644 --- a/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/flyoutmenu/components/FlyoutMenuComponentsPatch.kt @@ -25,12 +25,11 @@ import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -88,7 +87,7 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( // region patch for enable trim silence TrimSilenceConfigFingerprint.result?.let { - TrimSilenceConfigFingerprint.literalInstructionBooleanHook( + TrimSilenceConfigFingerprint.injectLiteralInstructionBooleanCall( 45619123, "$FLYOUT_CLASS_DESCRIPTOR->enableTrimSilence(Z)Z" ) @@ -96,9 +95,9 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( TrimSilenceSwitchFingerprint.resultOrThrow().let { it.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.TrimSilenceSwitch) + indexOfFirstWideLiteralInstructionValueOrThrow(SharedResourceIdPatch.TrimSilenceSwitch) val onCheckedChangedListenerIndex = - getTargetIndexOrThrow(constIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(constIndex, Opcode.INVOKE_DIRECT) val onCheckedChangedListenerReference = getInstruction(onCheckedChangedListenerIndex).reference val onCheckedChangedListenerDefiningClass = @@ -118,7 +117,7 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( && reference.parameterTypes[0] == "Z" } getWalkerMethod(context, walkerIndex).apply { - val insertIndex = getTargetIndexOrThrow(Opcode.MOVE_RESULT) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) val insertRegister = getInstruction(insertIndex).registerA @@ -142,7 +141,7 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( MenuItemFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val freeIndex = getTargetIndexOrThrow(Opcode.OR_INT_LIT16) + val freeIndex = indexOfFirstInstructionOrThrow(Opcode.OR_INT_LIT16) val textViewIndex = it.scanResult.patternScanResult!!.startIndex val imageViewIndex = it.scanResult.patternScanResult!!.endIndex @@ -175,8 +174,10 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( TouchOutsideFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setOnClickListener") + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val setOnClickListenerRegister = getInstruction(setOnClickListenerIndex).registerC @@ -189,8 +190,10 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( EndButtonsContainerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getWideLiteralInstructionIndex(EndButtonsContainer) - val targetIndex = getTargetIndexOrThrow(startIndex, Opcode.MOVE_RESULT_OBJECT) + val startIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(EndButtonsContainer) + val targetIndex = + indexOfFirstInstructionOrThrow(startIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt index 0c277ef54..f43d509f2 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/LayoutComponentsPatch.kt @@ -27,15 +27,17 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MusicTasteBuilderShelf +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerOverlayChip import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TopBarMenuItemImageView import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.patches.shared.settingmenu.SettingsMenuPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.alsoResolve +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -99,7 +101,7 @@ object LayoutComponentsPatch : BaseBytecodePatch( PlayerOverlayChipFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.PlayerOverlayChip) + 2 + indexOfFirstWideLiteralInstructionValueOrThrow(PlayerOverlayChip) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -176,8 +178,10 @@ object LayoutComponentsPatch : BaseBytecodePatch( if (SettingsPatch.upward0642) { TopBarMenuItemImageViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(TopBarMenuItemImageView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(TopBarMenuItemImageView) + val targetIndex = + indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -193,7 +197,7 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide sound search button SoundSearchFingerprint.result?.let { - SoundSearchFingerprint.literalInstructionBooleanHook( + SoundSearchFingerprint.injectLiteralInstructionBooleanCall( 45625491, "$GENERAL_CLASS_DESCRIPTOR->hideSoundSearchButton(Z)Z" ) @@ -227,8 +231,9 @@ object LayoutComponentsPatch : BaseBytecodePatch( parentResult.mutableMethod.apply { val constIndex = - getWideLiteralInstructionIndex(SharedResourceIdPatch.MusicTasteBuilderShelf) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + indexOfFirstWideLiteralInstructionValueOrThrow(MusicTasteBuilderShelf) + val targetIndex = + indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -263,14 +268,11 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button - SearchBarFingerprint.resolve( - context, - SearchBarParentFingerprint.resultOrThrow().classDef - ) - SearchBarFingerprint.resultOrThrow().let { + SearchBarFingerprint.alsoResolve( + context, SearchBarParentFingerprint + ).let { it.mutableMethod.apply { - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setVisibility") + val setVisibilityIndex = SearchBarFingerprint.indexOfVisibilityInstruction(this) val setVisibilityInstruction = getInstruction(setVisibilityIndex) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt index bbf6b50ce..b4a405384 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.music.general.components.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.HistoryMenuItem -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -16,7 +16,7 @@ internal object HistoryMenuItemFingerprint : MethodFingerprint( Opcode.RETURN_VOID ), customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(HistoryMenuItem) + methodDef.containsWideLiteralInstructionValue(HistoryMenuItem) && classDef.methods.count() == 5 } ) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt index e875e2be9..1453be5ea 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/HistoryMenuItemOfflineTabFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.HistoryMenuItem import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.OfflineSettingsMenuItem -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -17,7 +17,7 @@ internal object HistoryMenuItemOfflineTabFingerprint : MethodFingerprint( Opcode.RETURN_VOID ), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(HistoryMenuItem) - && methodDef.containsWideLiteralInstructionIndex(OfflineSettingsMenuItem) + methodDef.containsWideLiteralInstructionValue(HistoryMenuItem) + && methodDef.containsWideLiteralInstructionValue(OfflineSettingsMenuItem) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt index fbcd0ec91..3ba4a400b 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/components/fingerprints/SearchBarFingerprint.kt @@ -1,8 +1,22 @@ package app.revanced.patches.music.general.components.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.general.components.fingerprints.SearchBarFingerprint.indexOfVisibilityInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -object SearchBarFingerprint : MethodReferenceNameFingerprint( +object SearchBarFingerprint : MethodFingerprint( returnType = "V", - reference = { "setVisibility" } -) \ No newline at end of file + customFingerprint = { methodDef, _ -> + indexOfVisibilityInstruction(methodDef) >= 0 + } +) { + fun indexOfVisibilityInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt index de8629052..8201e0701 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/oldstylelibraryshelf/OldStyleLibraryShelfPatch.kt @@ -8,8 +8,8 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -27,8 +27,9 @@ object OldStyleLibraryShelfPatch : BaseBytecodePatch( BrowseIdFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getStringInstructionIndex("FEmusic_offline") - val targetIndex = getTargetIndexReversedOrThrow(stringIndex, Opcode.IGET_OBJECT) + val stringIndex = indexOfFirstStringInstructionOrThrow("FEmusic_offline") + val targetIndex = + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.IGET_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt b/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt index 703c0072b..fca2cf297 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/redirection/DislikeRedirectionPatch.kt @@ -11,11 +11,11 @@ import app.revanced.patches.music.utils.fingerprints.PendingIntentReceiverFinger import app.revanced.patches.music.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -41,13 +41,14 @@ object DislikeRedirectionPatch : BaseBytecodePatch( PendingIntentReceiverFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getStringInstructionIndex("YTM Dislike") + val startIndex = indexOfFirstStringInstructionOrThrow("YTM Dislike") val onClickRelayIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) val onClickRelayMethod = getWalkerMethod(context, onClickRelayIndex) onClickRelayMethod.apply { - val onClickMethodIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_DIRECT) + val onClickMethodIndex = + indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT) val onClickMethod = getWalkerMethod(context, onClickMethodIndex) onClickMethod.apply { @@ -70,7 +71,9 @@ object DislikeRedirectionPatch : BaseBytecodePatch( DislikeButtonOnClickListenerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val onClickIndex = getTargetIndexWithReferenceOrThrow(onClickReference.toString()) + val onClickIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == onClickReference.toString() + } injectCall(onClickIndex) } } @@ -84,7 +87,7 @@ object DislikeRedirectionPatch : BaseBytecodePatch( } private fun MutableMethod.injectCall(onClickIndex: Int) { - val targetIndex = getTargetIndexReversedOrThrow(onClickIndex, Opcode.IF_EQZ) + val targetIndex = indexOfFirstInstructionReversedOrThrow(onClickIndex, Opcode.IF_EQZ) val insertRegister = getInstruction(targetIndex).registerA addInstructionsWithLabels( diff --git a/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt index a405b7204..95a496b57 100644 --- a/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/general/redirection/fingerprints/DislikeButtonOnClickListenerFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.general.redirection.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object DislikeButtonOnClickListenerFingerprint : MethodFingerprint( @@ -10,7 +10,7 @@ internal object DislikeButtonOnClickListenerFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Landroid/view/View;"), customFingerprint = handler@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(53465)) + if (!methodDef.containsWideLiteralInstructionValue(53465)) return@handler false methodDef.name == "onClick" diff --git a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt index 8e95694bf..ed4e79c7f 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -10,15 +10,16 @@ import app.revanced.patches.music.misc.backgroundplayback.fingerprints.KidsBackg import app.revanced.patches.music.misc.backgroundplayback.fingerprints.MusicBrowserServiceFingerprint import app.revanced.patches.music.misc.backgroundplayback.fingerprints.PodCastConfigFingerprint import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.util.getStartsWithStringInstructionIndex -import app.revanced.util.getStringInstructionIndex +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object BackgroundPlaybackPatch : BaseBytecodePatch( @@ -51,26 +52,20 @@ object BackgroundPlaybackPatch : BaseBytecodePatch( // don't play music video MusicBrowserServiceFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = - getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s") - - for (index in targetIndex downTo 0) { - if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue - - val targetReference = getInstruction(index).reference - - if (!targetReference.toString().endsWith("()Z")) continue - - val walkerMethod = getWalkerMethod(context, index) - - walkerMethod.addInstructions( - 0, """ - const/4 v0, 0x1 - return v0 - """ - ) - break + val stringIndex = MusicBrowserServiceFingerprint.indexOfMBSInstruction(this) + val targetIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL && + reference?.returnType == "Z" && + reference.parameterTypes.size == 0 } + + getWalkerMethod(context, targetIndex).addInstructions( + 0, """ + const/4 v0, 0x1 + return v0 + """ + ) } } @@ -97,7 +92,8 @@ object BackgroundPlaybackPatch : BaseBytecodePatch( } dataSavingSettingsFragmentFingerprintResult!!.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("pref_key_dont_play_nma_video") + 4 + val insertIndex = + indexOfFirstStringInstructionOrThrow("pref_key_dont_play_nma_video") + 4 val targetRegister = getInstruction(insertIndex).registerD addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt index df191491c..2823a0079 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/backgroundplayback/fingerprints/MusicBrowserServiceFingerprint.kt @@ -2,8 +2,13 @@ package app.revanced.patches.music.misc.backgroundplayback.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.getStartsWithStringInstructionIndex +import app.revanced.patches.music.misc.backgroundplayback.fingerprints.MusicBrowserServiceFingerprint.indexOfMBSInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.StringReference internal object MusicBrowserServiceFingerprint : MethodFingerprint( returnType = "L", @@ -13,6 +18,12 @@ internal object MusicBrowserServiceFingerprint : MethodFingerprint( if (!methodDef.definingClass.endsWith("/MusicBrowserService;")) return@custom false - methodDef.getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s") > 0 + indexOfMBSInstruction(methodDef) >= 0 } -) \ No newline at end of file +) { + fun indexOfMBSInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + opcode == Opcode.CONST_STRING && + getReference()?.string?.startsWith("MBS: Return empty root for client: %s") == true + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt index 204d168a0..8a3b9b0a5 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/share/ShareSheetPatch.kt @@ -12,8 +12,8 @@ import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.BottomS import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.patches.shared.litho.LithoFilterPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -40,8 +40,8 @@ object ShareSheetPatch : BaseBytecodePatch( override fun execute(context: BytecodeContext) { BottomSheetRecyclerViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(BottomSheetRecyclerView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(BottomSheetRecyclerView) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt index ae0465ae4..e5c9b45ee 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/splash/CairoSplashAnimationPatch.kt @@ -8,7 +8,7 @@ import app.revanced.patches.music.misc.splash.fingerprints.CairoSplashAnimationC import app.revanced.patches.music.utils.integrations.Constants.MISC_PATH import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( name = "Disable Cairo splash animation", @@ -31,7 +31,7 @@ object CairoSplashAnimationPatch : BytecodePatch( override fun execute(context: BytecodeContext) { CairoSplashAnimationConfigFingerprint.result?.let { - CairoSplashAnimationConfigFingerprint.literalInstructionBooleanHook( + CairoSplashAnimationConfigFingerprint.injectLiteralInstructionBooleanCall( 45635386, "$MISC_PATH/CairoSplashAnimationPatch;->disableCairoSplashAnimation(Z)Z" ) diff --git a/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt index adcd24adf..a2e16a724 100644 --- a/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/navigation/components/NavigationBarComponentsPatch.kt @@ -11,13 +11,12 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA import app.revanced.patches.music.utils.integrations.Constants.NAVIGATION_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.Text1 import app.revanced.patches.music.utils.settings.CategoryType import app.revanced.patches.music.utils.settings.SettingsPatch import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -50,7 +49,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( * Enable black navigation bar */ TabLayoutFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ColorGrey) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ColorGrey) val insertIndex = indexOfFirstInstructionOrThrow(constIndex) { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.name == "setBackgroundColor" @@ -70,8 +69,9 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( */ TabLayoutTextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(SharedResourceIdPatch.Text1) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(Text1) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetParameter = getInstruction(targetIndex).reference val targetRegister = getInstruction(targetIndex).registerA @@ -105,9 +105,12 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { val enumIndex = it.scanResult.patternScanResult!!.startIndex + 3 val enumRegister = getInstruction(enumIndex).registerA - val insertEnumIndex = getTargetIndexOrThrow(Opcode.AND_INT_LIT8) - 2 + val insertEnumIndex = indexOfFirstInstructionOrThrow(Opcode.AND_INT_LIT8) - 2 - val pivotTabIndex = getTargetIndexWithMethodReferenceNameOrThrow("getVisibility") + val pivotTabIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "getVisibility" + } val pivotTabRegister = getInstruction(pivotTabIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt index 8bc50eed1..32ef4bde4 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/PlayerComponentsPatch.kt @@ -60,16 +60,13 @@ import app.revanced.patches.music.utils.videotype.VideoTypeHookPatch import app.revanced.patches.shared.litho.LithoFilterPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.transformFields @@ -145,8 +142,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( PlayerViewPager to "disablePlayerGesture" ).forEach { (literal, methodName) -> val viewPagerReference = playerViewPagerConstructorMethod.let { - val constIndex = it.getWideLiteralInstructionIndex(literal) - val targetIndex = it.getTargetIndexOrThrow(constIndex, Opcode.IPUT_OBJECT) + val constIndex = it.indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = it.indexOfFirstInstructionOrThrow(constIndex, Opcode.IPUT_OBJECT) it.getInstruction(targetIndex).reference.toString() } @@ -156,7 +153,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( && getReference()?.toString() == viewPagerReference } val insertRegister = getInstruction(insertIndex).registerA - val jumpIndex = getTargetIndex(insertIndex, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(insertIndex, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( insertIndex, """ @@ -198,8 +196,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( val relativeIndex = it.scanResult.patternScanResult!!.endIndex + 1 val invokeVirtualIndex = - getTargetIndexOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL) - val iGetIndex = getTargetIndexOrThrow(relativeIndex, Opcode.IGET) + indexOfFirstInstructionOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL) + val iGetIndex = indexOfFirstInstructionOrThrow(relativeIndex, Opcode.IGET) colorMathPlayerInvokeVirtualReference = getInstruction(invokeVirtualIndex).reference @@ -207,11 +205,11 @@ object PlayerComponentsPatch : BaseBytecodePatch( getInstruction(iGetIndex).reference // black player background - val invokeDirectIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT) val targetMethod = getWalkerMethod(context, invokeDirectIndex) targetMethod.apply { - val insertIndex = getTargetIndexOrThrow(0, Opcode.IF_NE) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IF_NE) addInstructions( insertIndex, """ @@ -225,8 +223,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( } parentResult.mutableMethod.apply { - val colorGreyIndex = getWideLiteralInstructionIndex(ColorGrey) - val iPutIndex = getTargetIndexOrThrow(colorGreyIndex, Opcode.IPUT) + val colorGreyIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ColorGrey) + val iPutIndex = indexOfFirstInstructionOrThrow(colorGreyIndex, Opcode.IPUT) colorMathPlayerIPutReference = getInstruction(iPutIndex).reference @@ -240,7 +238,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 3 - val invokeDirectIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = + indexOfFirstInstructionReversedOrThrow(Opcode.INVOKE_DIRECT) val invokeDirectReference = getInstruction(invokeDirectIndex).reference @@ -401,9 +400,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( reversed: Boolean ): Reference { val targetIndex = if (reversed) - getTargetIndexReversedOrThrow(swipeToDismissWidgetIndex, opcode) + indexOfFirstInstructionReversedOrThrow(swipeToDismissWidgetIndex, opcode) else - getTargetIndexOrThrow(swipeToDismissWidgetIndex, opcode) + indexOfFirstInstructionOrThrow(swipeToDismissWidgetIndex, opcode) return getInstruction(targetIndex).reference } @@ -411,7 +410,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( if (!SettingsPatch.upward0642) { SwipeToCloseFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = implementation!!.instructions.size - 1 + val insertIndex = implementation!!.instructions.lastIndex val targetRegister = getInstruction(insertIndex).registerA @@ -430,8 +429,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( InteractionLoggingEnumFingerprint.resultOrThrow().let { it.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE") - val sPutObjectIndex = getTargetIndexOrThrow(stringIndex, Opcode.SPUT_OBJECT) + indexOfFirstStringInstructionOrThrow("INTERACTION_LOGGING_GESTURE_TYPE_SWIPE") + val sPutObjectIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.SPUT_OBJECT) swipeToDismissSGetObjectReference = getInstruction(sPutObjectIndex).reference @@ -440,7 +440,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( MusicActivityWidgetFingerprint.resultOrThrow().let { it.mutableMethod.apply { - swipeToDismissWidgetIndex = getWideLiteralInstructionIndex(79500) + swipeToDismissWidgetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(79500) swipeToDismissIGetObjectReference = getSwipeToDismissReference(Opcode.IGET_OBJECT, true) @@ -468,8 +469,9 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.getWalkerMethod(context, it.scanResult.patternScanResult!!.startIndex) dismissBehaviorMethod.apply { - val insertIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Ljava/util/concurrent/atomic/AtomicBoolean;") + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Ljava/util/concurrent/atomic/AtomicBoolean;" + } val primaryRegister = getInstruction(insertIndex).registerB val secondaryRegister = primaryRegister + 1 @@ -592,7 +594,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( SwitchToggleColorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val invokeDirectIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT) + val invokeDirectIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT) val walkerMethod = getWalkerMethod(context, invokeDirectIndex) walkerMethod.addInstructions( @@ -624,8 +626,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for hide audio video switch toggle AudioVideoSwitchToggleFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AudioVideoSwitchToggle) - val viewIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AudioVideoSwitchToggle) + val viewIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val viewRegister = getInstruction(viewIndex).registerA addInstruction( @@ -667,7 +669,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( DarkBackground, TapBloomView ).forEach { literal -> - QuickSeekOverlayFingerprint.literalInstructionViewHook( + QuickSeekOverlayFingerprint.injectLiteralInstructionViewCall( literal, smaliInstruction ) @@ -742,9 +744,10 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableMethod.apply { rememberShuffleStateObjectClass = definingClass - val constIndex = getWideLiteralInstructionIndex(45468) - val iGetObjectIndex = getTargetIndexOrThrow(constIndex, Opcode.IGET_OBJECT) - val checkCastIndex = getTargetIndexOrThrow(iGetObjectIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45468) + val iGetObjectIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IGET_OBJECT) + val checkCastIndex = + indexOfFirstInstructionOrThrow(iGetObjectIndex, Opcode.CHECK_CAST) val ordinalIndex = indexOfOrdinalInstruction(this) val imageViewIndex = indexOfImageViewInstruction(this) @@ -888,7 +891,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old comments popup panels OldEngagementPanelFingerprint.result?.let { - OldEngagementPanelFingerprint.literalInstructionBooleanHook( + OldEngagementPanelFingerprint.injectLiteralInstructionBooleanCall( 45427672, "$PLAYER_CLASS_DESCRIPTOR->restoreOldCommentsPopUpPanels(Z)Z" ) @@ -905,7 +908,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old player background OldPlayerBackgroundFingerprint.result?.let { - OldPlayerBackgroundFingerprint.literalInstructionBooleanHook( + OldPlayerBackgroundFingerprint.injectLiteralInstructionBooleanCall( 45415319, "$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerBackground(Z)Z" ) @@ -922,7 +925,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( // region patch for restore old player layout OldPlayerLayoutFingerprint.result?.let { - OldPlayerLayoutFingerprint.literalInstructionBooleanHook( + OldPlayerLayoutFingerprint.injectLiteralInstructionBooleanCall( 45399578, "$PLAYER_CLASS_DESCRIPTOR->restoreOldPlayerLayout(Z)Z" ) @@ -943,11 +946,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( viewId: Long ) { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val miniPlayerPlayPauseReplayButtonRegister = getInstruction(miniPlayerPlayPauseReplayButtonIndex).registerA val findViewByIdIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_VIRTUAL + ) val parentViewRegister = getInstruction(findViewByIdIndex).registerC @@ -966,11 +972,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( viewId: Long ) { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val constRegister = getInstruction(miniPlayerPlayPauseReplayButtonIndex).registerA val findViewByIdIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_VIRTUAL) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_VIRTUAL + ) val findViewByIdRegister = getInstruction(findViewByIdIndex).registerC @@ -986,9 +995,12 @@ object PlayerComponentsPatch : BaseBytecodePatch( private fun MutableMethod.setViewArray() { val miniPlayerPlayPauseReplayButtonIndex = - getWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + indexOfFirstWideLiteralInstructionValueOrThrow(MiniPlayerPlayPauseReplayButton) val invokeStaticIndex = - getTargetIndexOrThrow(miniPlayerPlayPauseReplayButtonIndex, Opcode.INVOKE_STATIC) + indexOfFirstInstructionOrThrow( + miniPlayerPlayPauseReplayButtonIndex, + Opcode.INVOKE_STATIC + ) val viewArrayRegister = getInstruction(invokeStaticIndex).registerC addInstructions( @@ -1005,8 +1017,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( methodName: String, fieldName: String ) { - val startIndex = getStringInstructionIndex(intentString) - val onClickIndex = getTargetIndexReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) + val startIndex = indexOfFirstStringInstructionOrThrow(intentString) + val onClickIndex = indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.INVOKE_VIRTUAL) val onClickReference = getInstruction(onClickIndex).reference val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass @@ -1016,7 +1028,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( onClickClass.methods.find { method -> method.name == "" } ?.apply { addInstruction( - implementation!!.instructions.size - 1, + implementation!!.instructions.lastIndex, "sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass" ) } ?: throw PatchException("onClickClass not found!") diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt index 3ac11537f..57ec8f975 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MiniPlayerConstructorFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.ColorGrey import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object MiniPlayerConstructorFingerprint : MethodFingerprint( returnType = "V", strings = listOf("sharedToggleMenuItemMutations"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ColorGrey) - && methodDef.containsWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + methodDef.containsWideLiteralInstructionValue(ColorGrey) + && methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt index a7e57557d..8cc697b71 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MppWatchWhileLayoutFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerPlayPauseReplayButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode internal object MppWatchWhileLayoutFingerprint : MethodFingerprint( @@ -11,6 +11,6 @@ internal object MppWatchWhileLayoutFingerprint : MethodFingerprint( customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/MppWatchWhileLayout;") && methodDef.name == "onFinishInflate" - && methodDef.containsWideLiteralInstructionIndex(MiniPlayerPlayPauseReplayButton) + && methodDef.containsWideLiteralInstructionValue(MiniPlayerPlayPauseReplayButton) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt index 0eb77a374..32c5106e4 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/MusicActivityWidgetFingerprint.kt @@ -1,13 +1,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object MusicActivityWidgetFingerprint : MethodFingerprint( customFingerprint = handler@{ methodDef, _ -> if (!methodDef.definingClass.endsWith("/MusicActivity;")) return@handler false - methodDef.containsWideLiteralInstructionIndex(79500) + methodDef.containsWideLiteralInstructionValue(79500) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt index 9a2116941..e1ad8bc6b 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/PlayerViewPagerConstructorFingerprint.kt @@ -4,14 +4,14 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.MiniPlayerViewPager import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.PlayerViewPager -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerViewPagerConstructorFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(MiniPlayerViewPager) - && methodDef.containsWideLiteralInstructionIndex(PlayerViewPager) + methodDef.containsWideLiteralInstructionValue(MiniPlayerViewPager) + && methodDef.containsWideLiteralInstructionValue(PlayerViewPager) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt index 89714d3b2..1e2add9d4 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/QuickSeekOverlayFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.music.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.DarkBackground import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TapBloomView -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object QuickSeekOverlayFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(DarkBackground) - && methodDef.containsWideLiteralInstructionIndex(TapBloomView) + methodDef.containsWideLiteralInstructionValue(DarkBackground) + && methodDef.containsWideLiteralInstructionValue(TapBloomView) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt index 64f792f24..6fb14779c 100644 --- a/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/player/components/fingerprints/ShuffleClassReferenceFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfImageViewInstruction import app.revanced.patches.music.player.components.fingerprints.ShuffleClassReferenceFingerprint.indexOfOrdinalInstruction -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags @@ -19,7 +19,7 @@ internal object ShuffleClassReferenceFingerprint : MethodFingerprint( parameters = emptyList(), strings = listOf("Unknown shuffle mode"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(45468) && + methodDef.containsWideLiteralInstructionValue(45468) && indexOfOrdinalInstruction(methodDef) >= 0 && indexOfImageViewInstruction(methodDef) >= 0 } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt deleted file mode 100644 index 5dd6b7a7b..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/AccessibilityNodeInfoPatch.kt +++ /dev/null @@ -1,60 +0,0 @@ -package app.revanced.patches.music.utils.fix.accessibility - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patches.music.utils.fix.accessibility.fingerprints.TouchExplorationHoverEventFingerprint -import app.revanced.util.containsMethodReferenceNameInstructionIndex -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference - -object AccessibilityNodeInfoPatch : BytecodePatch( - setOf(TouchExplorationHoverEventFingerprint) -) { - override fun execute(context: BytecodeContext) { - - /** - * The "getTouchDelegateInfo" method has been implemented in YT Music v6.44.52. - * For some reason this method sometimes returns null, which throws [IllegalArgumentException]. - * This is considered unimplemented code, so remove all methods associated with it. - */ - TouchExplorationHoverEventFingerprint.result?.let { - it.mutableMethod.apply { - // Target instruction is invoke-static, but can also be invoke-virtual. - // Therefore, the opcode is not checked. - val touchExplorationHoverEventMethodIndex = - implementation!!.instructions.indexOfFirst { instruction -> - val reference = - ((instruction as? ReferenceInstruction)?.reference as? MethodReference) - ((instruction as? ReferenceInstruction)?.reference as? MethodReference)?.definingClass == definingClass - && reference?.returnType == "Z" - } - - // Doesn't raise an exception, even if the target instruction is not found in this method - val touchExplorationHoverEventMethodName = - if (touchExplorationHoverEventMethodIndex > -1) - (getInstruction(touchExplorationHoverEventMethodIndex).reference as MethodReference).name - else - "UNDEFINED" - - val methods = it.mutableClass.methods - - methods.find { method -> - method.name == "getTouchDelegateInfo" - }?.apply { - if (!containsMethodReferenceNameInstructionIndex("isEmpty")) { - arrayOf( - "getTouchDelegateInfo", - name, - touchExplorationHoverEventMethodName - ).forEach { methodName -> - methods.removeIf { method -> - method.name == methodName - } - } - } - } - } - } // If this method has not been added, there is no need to remove it, so it will not raise any exceptions. - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt deleted file mode 100644 index 97920323e..000000000 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/accessibility/fingerprints/TouchExplorationHoverEventFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.music.utils.fix.accessibility.fingerprints - -import app.revanced.patcher.fingerprint.MethodFingerprint - -internal object TouchExplorationHoverEventFingerprint : MethodFingerprint( - returnType = "Z", - customFingerprint = { methodDef, _ -> methodDef.name == "onTouchExplorationHoverEvent" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt index 907fdeb5f..c95ad1965 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/fix/header/RestoreOldHeaderPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.music.utils.fix.header import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.layout.header.ChangeHeaderPatch import app.revanced.patches.music.utils.fix.header.fingerprints.HeaderSwitchConfigFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fix the issues where new headers are used." @@ -31,19 +26,10 @@ object RestoreOldHeaderPatch : BytecodePatch( * TODO: Add a new header image file to [ChangeHeaderPatch] later. */ HeaderSwitchConfigFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45617851), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + HeaderSwitchConfigFingerprint.injectLiteralInstructionBooleanCall( + 45617851, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt index d78940ff1..e3a25fead 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsBytecodePatch.kt @@ -17,7 +17,7 @@ import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerpr import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -52,7 +52,7 @@ object SettingsBytecodePatch : BytecodePatch( */ SharedSettingFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getTargetIndexOrThrow(Opcode.CONST_STRING) + val stringIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) val stringRegister = getInstruction(stringIndex).registerA replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt index f00dc88f6..b5fb0b28f 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/settings/SettingsPatch.kt @@ -3,7 +3,6 @@ package app.revanced.patches.music.utils.settings import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE -import app.revanced.patches.music.utils.fix.accessibility.AccessibilityNodeInfoPatch import app.revanced.patches.music.utils.settings.ResourceUtils.addPreferenceCategory import app.revanced.patches.music.utils.settings.ResourceUtils.addPreferenceWithIntent import app.revanced.patches.music.utils.settings.ResourceUtils.addRVXSettingsPreference @@ -22,10 +21,7 @@ import java.util.concurrent.TimeUnit object SettingsPatch : BaseResourcePatch( name = "Settings for YouTube Music", description = "Applies mandatory patches to implement ReVanced Extended settings into the application.", - dependencies = setOf( - AccessibilityNodeInfoPatch::class, - SettingsBytecodePatch::class - ), + dependencies = setOf(SettingsBytecodePatch::class), compatiblePackages = COMPATIBLE_PACKAGE, requiresIntegrations = true ), Closeable { diff --git a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt index adce2aba8..8845cc5e0 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/sponsorblock/SponsorBlockBytecodePatch.kt @@ -14,13 +14,17 @@ import app.revanced.patches.music.utils.sponsorblock.fingerprints.MusicPlaybackC import app.revanced.patches.music.utils.sponsorblock.fingerprints.SeekbarOnDrawFingerprint import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.patches.music.video.videoid.VideoIdPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( dependencies = [ @@ -55,10 +59,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( /** * Responsible for seekbar in fullscreen */ - val seekBarClass = SeekBarConstructorFingerprint.resultOrThrow().mutableClass - SeekbarOnDrawFingerprint.resolve(context, seekBarClass) - - SeekbarOnDrawFingerprint.resultOrThrow().let { + SeekbarOnDrawFingerprint.alsoResolve( + context, SeekBarConstructorFingerprint + ).let { it.mutableMethod.apply { // Initialize seekbar method addInstructions( @@ -70,7 +73,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Set seekbar thickness - val roundIndex = getTargetIndexWithMethodReferenceNameOrThrow("round") + 1 + val roundIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "round" + } + 1 val roundRegister = getInstruction(roundIndex).registerA addInstruction( roundIndex + 1, @@ -79,8 +84,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, @@ -115,7 +121,10 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = getTargetIndexWithMethodReferenceNameOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + && getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, diff --git a/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt index 53cd1e098..5b3e02e5f 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/information/VideoInformationPatch.kt @@ -26,10 +26,9 @@ import app.revanced.patches.music.video.videoid.VideoIdPatch import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint import app.revanced.util.addFieldAndInstructions import app.revanced.util.getReference -import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -216,12 +215,10 @@ object VideoInformationPatch : BytecodePatch( ) VideoLengthFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val invalidateIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("invalidate") - val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversedOrThrow( - invalidateIndex + 1, - "Landroid/graphics/Rect;" - ) + val invalidateIndex = VideoLengthFingerprint.indexOfInvalidateInstruction(this) + val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } rectangleFieldName = (getInstruction(rectangleIndex).reference as FieldReference).name diff --git a/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt index 09da6b37d..293b0f1ed 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/information/fingerprints/VideoLengthFingerprint.kt @@ -1,9 +1,14 @@ package app.revanced.patches.music.video.information.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.music.video.information.fingerprints.VideoLengthFingerprint.indexOfInvalidateInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object VideoLengthFingerprint : MethodReferenceNameFingerprint( +internal object VideoLengthFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_WIDE, @@ -12,5 +17,12 @@ internal object VideoLengthFingerprint : MethodReferenceNameFingerprint( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_WIDE ), - reference = { "invalidate" } -) \ No newline at end of file + customFingerprint = { methodDef, _ -> + indexOfInvalidateInstruction(methodDef) >= 0 + } +) { + fun indexOfInvalidateInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "invalidate" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt index 4173158b0..1b064ec81 100644 --- a/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/video/playback/VideoPlaybackPatch.kt @@ -13,7 +13,7 @@ import app.revanced.patches.music.video.information.VideoInformationPatch import app.revanced.patches.music.video.playback.fingerprints.PlaybackSpeedBottomSheetFingerprint import app.revanced.patches.music.video.playback.fingerprints.UserQualityChangeFingerprint import app.revanced.patches.music.video.videoid.VideoIdPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -52,7 +52,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "onItemClick" } onItemClickMethod?.apply { - val targetIndex = getTargetIndexOrThrow(Opcode.IGET) + val targetIndex = indexOfFirstInstructionOrThrow(Opcode.IGET) val targetRegister = getInstruction(targetIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt index de989f069..dd2595576 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/ad/general/AdsPatch.kt @@ -12,12 +12,15 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithFieldReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object AdsPatch : BaseBytecodePatch( @@ -42,7 +45,9 @@ object AdsPatch : BaseBytecodePatch( // region Filter promoted ads (does not work in popular or latest feed) AdPostFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithFieldReferenceNameOrThrow("children") + val targetIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "children" + } val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -59,7 +64,10 @@ object AdsPatch : BaseBytecodePatch( // By removing the appending instruction no ad posts gets appended to the feed. NewAdPostFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("add") + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + && getReference()?.toString() == "Ljava/util/ArrayList;->add(Ljava/lang/Object;)Z" + } val targetInstruction = getInstruction(targetIndex) replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt index d9338e274..8956f23e0 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/recentlyvisited/RecentlyVisitedShelfPatch.kt @@ -9,15 +9,15 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.Reference @Suppress("unused") @@ -40,20 +40,31 @@ object RecentlyVisitedShelfPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "" } ?.apply { - val recentlyVisitedFieldIndex = - getTargetIndexWithFieldReferenceNameOrThrow("RECENTLY_VISITED") + val recentlyVisitedFieldIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "RECENTLY_VISITED" + } val recentlyVisitedObjectIndex = - getTargetIndexOrThrow(recentlyVisitedFieldIndex, Opcode.IPUT_OBJECT) + indexOfFirstInstructionOrThrow( + recentlyVisitedFieldIndex, + Opcode.IPUT_OBJECT + ) recentlyVisitedReference = getInstruction(recentlyVisitedObjectIndex).reference } ?: throw PatchException("Constructor method not found!") it.mutableMethod.apply { - val recentlyVisitedObjectIndex = - getTargetIndexWithReferenceOrThrow(recentlyVisitedReference.toString()) + val recentlyVisitedObjectIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == recentlyVisitedReference.toString() + } arrayOf( - getTargetIndexOrThrow(recentlyVisitedObjectIndex, Opcode.INVOKE_STATIC), - getTargetIndexReversedOrThrow(recentlyVisitedObjectIndex, Opcode.INVOKE_STATIC) + indexOfFirstInstructionOrThrow( + recentlyVisitedObjectIndex, + Opcode.INVOKE_STATIC + ), + indexOfFirstInstructionReversedOrThrow( + recentlyVisitedObjectIndex, + Opcode.INVOKE_STATIC + ) ).forEach { staticIndex -> val insertRegister = getInstruction(staticIndex + 1).registerA diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt index 541efade0..6154e8669 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/screenshotpopup/fingerprints/ScreenshotTakenBannerFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.screenshotpopup.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ScreenShotShareBanner -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object ScreenshotTakenBannerFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(ScreenShotShareBanner) + methodDef.containsWideLiteralInstructionValue(ScreenShotShareBanner) && classDef.sourceFile == "ScreenshotTakenBanner.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt index ebc2f2e65..83adfb7b0 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/SubRedditDialogPatch.kt @@ -12,7 +12,7 @@ import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.Cancel import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.TextAppearanceRedditBaseOldButtonColored import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -39,7 +39,8 @@ object SubRedditDialogPatch : BaseBytecodePatch( FrequentUpdatesSheetScreenFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val cancelButtonViewIndex = getWideLiteralInstructionIndex(CancelButton) + 2 + val cancelButtonViewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(CancelButton) + 2 val cancelButtonViewRegister = getInstruction(cancelButtonViewIndex).registerA @@ -53,7 +54,9 @@ object SubRedditDialogPatch : BaseBytecodePatch( RedditAlertDialogsFingerprint.resultOrThrow().let { it.mutableMethod.apply { val insertIndex = - getWideLiteralInstructionIndex(TextAppearanceRedditBaseOldButtonColored) + 1 + indexOfFirstWideLiteralInstructionValueOrThrow( + TextAppearanceRedditBaseOldButtonColored + ) + 1 val insertRegister = getInstruction(insertIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt index 33e648aac..ab8942a7b 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/FrequentUpdatesSheetScreenFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.subredditdialog.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.CancelButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object FrequentUpdatesSheetScreenFingerprint : MethodFingerprint( returnType = "Landroid/view/View;", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(CancelButton) + methodDef.containsWideLiteralInstructionValue(CancelButton) && classDef.sourceFile == "FrequentUpdatesSheetScreen.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt index 44515f97b..a992cad69 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/subredditdialog/fingerprints/RedditAlertDialogsFingerprint.kt @@ -3,14 +3,14 @@ package app.revanced.patches.reddit.layout.subredditdialog.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.TextAppearanceRedditBaseOldButtonColored -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object RedditAlertDialogsFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, classDef -> - methodDef.containsWideLiteralInstructionIndex(TextAppearanceRedditBaseOldButtonColored) + methodDef.containsWideLiteralInstructionValue(TextAppearanceRedditBaseOldButtonColored) && classDef.sourceFile == "RedditAlertDialogs.kt" } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt index d71fc2f39..f2a305f20 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/ToolBarButtonPatch.kt @@ -10,7 +10,7 @@ import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ToolBarNavSearchCtaContainer import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -35,7 +35,7 @@ object ToolBarButtonPatch : BaseBytecodePatch( HomePagerScreenFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = - getWideLiteralInstructionIndex(ToolBarNavSearchCtaContainer) + 3 + indexOfFirstWideLiteralInstructionValueOrThrow(ToolBarNavSearchCtaContainer) + 3 val targetRegister = getInstruction(targetIndex - 1).registerA diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt index 4f42a5df8..ecec1bce5 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/layout/toolbar/fingerprints/HomePagerScreenFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.layout.toolbar.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.ToolBarNavSearchCtaContainer -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object HomePagerScreenFingerprint : MethodFingerprint( @@ -12,6 +12,6 @@ internal object HomePagerScreenFingerprint : MethodFingerprint( parameters = listOf("Landroid/view/LayoutInflater;", "Landroid/view/ViewGroup;"), customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("/HomePagerScreen;") - && methodDef.containsWideLiteralInstructionIndex(ToolBarNavSearchCtaContainer) + && methodDef.containsWideLiteralInstructionValue(ToolBarNavSearchCtaContainer) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt index fb1850579..5a9e81681 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/misc/openlink/OpenLinksExternallyPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patches.reddit.utils.compatibility.Constants.COMPATIBLE_PACK import app.revanced.patches.reddit.utils.integrations.Constants.PATCHES_PATH import app.revanced.patches.reddit.utils.settings.SettingsBytecodePatch.updateSettingsStatus import app.revanced.patches.reddit.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow @@ -27,7 +27,7 @@ object OpenLinksExternallyPatch : BaseBytecodePatch( override fun execute(context: BytecodeContext) { ScreenNavigatorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("uri") + 2 + val insertIndex = indexOfFirstStringInstructionOrThrow("uri") + 2 addInstructionsWithLabels( insertIndex, """ diff --git a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt index cf6aa5851..cd1513922 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/SettingsBytecodePatch.kt @@ -15,8 +15,8 @@ import app.revanced.patches.reddit.utils.settings.fingerprints.AcknowledgementsL import app.revanced.patches.reddit.utils.settings.fingerprints.OssLicensesMenuActivityOnCreateFingerprint import app.revanced.patches.reddit.utils.settings.fingerprints.SettingsStatusLoadFingerprint import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -39,7 +39,7 @@ object SettingsBytecodePatch : BytecodePatch( internal fun updateSettingsLabel(label: String) = acknowledgementsLabelBuilderMethod.apply { val insertIndex = - getWideLiteralInstructionIndex(LabelAcknowledgements) + 3 + indexOfFirstWideLiteralInstructionValueOrThrow(LabelAcknowledgements) + 3 val insertRegister = getInstruction(insertIndex - 1).registerA @@ -62,7 +62,7 @@ object SettingsBytecodePatch : BytecodePatch( */ SharedSettingFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val stringIndex = getTargetIndexOrThrow(Opcode.CONST_STRING) + val stringIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) val stringRegister = getInstruction(stringIndex).registerA replaceInstruction( diff --git a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt index 6954a037c..6bccc6594 100644 --- a/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/reddit/utils/settings/fingerprints/AcknowledgementsLabelBuilderFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.reddit.utils.settings.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.LabelAcknowledgements -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object AcknowledgementsLabelBuilderFingerprint : MethodFingerprint( @@ -12,6 +12,6 @@ internal object AcknowledgementsLabelBuilderFingerprint : MethodFingerprint( parameters = listOf("Landroidx/preference/Preference;"), customFingerprint = { methodDef, _ -> methodDef.definingClass.startsWith("Lcom/reddit/screen/settings/preferences/") - && methodDef.containsWideLiteralInstructionIndex(LabelAcknowledgements) + && methodDef.containsWideLiteralInstructionValue(LabelAcknowledgements) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt index 90e3f1a80..1988df271 100644 --- a/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt @@ -14,8 +14,8 @@ import app.revanced.patches.shared.ads.fingerprints.VideoAdsFingerprint import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -75,7 +75,7 @@ abstract class BaseAdsPatch( internal fun MethodFingerprintResult.hookNonLithoFullscreenAds(literal: Long) { mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(literal) + 2 + val targetIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + 2 val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt index ca1e9b1de..b2e29869b 100644 --- a/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/customspeed/BaseCustomPlaybackSpeedPatch.kt @@ -8,14 +8,14 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patches.shared.customspeed.fingerprints.SpeedArrayGeneratorFingerprint import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFallBackFingerprint import app.revanced.patches.shared.customspeed.fingerprints.SpeedLimiterFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference abstract class BaseCustomPlaybackSpeedPatch( private val descriptor: String, @@ -39,7 +39,9 @@ abstract class BaseCustomPlaybackSpeedPatch( """ ) - val sizeIndex = getTargetIndexWithMethodReferenceNameOrThrow("size") + 1 + val sizeIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "size" + } + 1 val sizeRegister = getInstruction(sizeIndex).registerA addInstructions( @@ -49,7 +51,9 @@ abstract class BaseCustomPlaybackSpeedPatch( """ ) - val arrayIndex = getTargetIndexWithFieldReferenceTypeOrThrow("[F") + val arrayIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "[F" + } val arrayRegister = getInstruction(arrayIndex).registerA addInstructions( @@ -73,7 +77,7 @@ abstract class BaseCustomPlaybackSpeedPatch( val limiterMinConstIndex = indexOfFirstInstructionOrThrow { (this as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() } val limiterMaxConstIndex = - getTargetIndexOrThrow(limiterMinConstIndex + 1, Opcode.CONST_HIGH16) + indexOfFirstInstructionOrThrow(limiterMinConstIndex + 1, Opcode.CONST_HIGH16) val limiterMinConstDestination = getInstruction(limiterMinConstIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt b/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt index 93473d2ba..79000567e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/dialog/BaseViewerDiscretionDialogPatch.kt @@ -7,10 +7,12 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.dialog.fingerprints.CreateDialogFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference abstract class BaseViewerDiscretionDialogPatch( private val classDescriptor: String, @@ -22,7 +24,9 @@ abstract class BaseViewerDiscretionDialogPatch( } ) { private fun MutableMethod.invoke(isAgeVerified: Boolean) { - val showDialogIndex = getTargetIndexWithMethodReferenceNameOrThrow("show") + val showDialogIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "show" + } val dialogRegister = getInstruction(showDialogIndex).registerC val methodName = diff --git a/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt b/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt index cf7ee092d..c0c53cf1e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/drawable/DrawableColorPatch.kt @@ -6,9 +6,11 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.drawable.fingerprints.DrawableFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference object DrawableColorPatch : BytecodePatch( setOf(DrawableFingerprint) @@ -17,26 +19,26 @@ object DrawableColorPatch : BytecodePatch( DrawableFingerprint.resultOrThrow().mutableMethod.apply { insertMethod = this - insertIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow("setColor") + insertIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "setColor" + } insertRegister = getInstruction(insertIndex).registerD } } - private var offset = 0 - + private lateinit var insertMethod: MutableMethod private var insertIndex: Int = 0 private var insertRegister: Int = 0 - private lateinit var insertMethod: MutableMethod - + private var offset = 0 fun injectCall( methodDescriptor: String ) { insertMethod.addInstructions( insertIndex + offset, """ - invoke-static {v$insertRegister}, $methodDescriptor - move-result v$insertRegister - """ + invoke-static {v$insertRegister}, $methodDescriptor + move-result v$insertRegister + """ ) offset += 2 } diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt index 082c25e90..542b491e0 100644 --- a/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/BaseGmsCoreSupportPatch.kt @@ -18,14 +18,12 @@ import app.revanced.patches.shared.gms.fingerprints.CastContextFetchFingerprint import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleFingerprint import app.revanced.patches.shared.gms.fingerprints.CastDynamiteModuleV2Fingerprint import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint -import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE import app.revanced.patches.shared.gms.fingerprints.GmsCoreSupportFingerprint import app.revanced.patches.shared.gms.fingerprints.GooglePlayUtilityFingerprint import app.revanced.patches.shared.gms.fingerprints.PrimeMethodFingerprint import app.revanced.patches.shared.gms.fingerprints.ServiceCheckFingerprint import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.util.getReference -import app.revanced.util.getTargetIndexWithReference import app.revanced.util.resultOrThrow import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.Opcode @@ -178,7 +176,7 @@ abstract class BaseGmsCoreSupportPatch( CertificateFingerprint.result?.mutableClass?.methods?.forEach { mutableMethod -> mutableMethod.apply { val getPackageNameIndex = - getTargetIndexWithReference(GET_PACKAGE_NAME_METHOD_REFERENCE) + CertificateFingerprint.indexOfGetPackageNameInstruction(this) if (getPackageNameIndex > -1) { val targetRegister = diff --git a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt index 0632e3b1f..29d08c178 100644 --- a/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/gms/fingerprints/CertificateFingerprint.kt @@ -1,20 +1,28 @@ package app.revanced.patches.shared.gms.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.GET_PACKAGE_NAME_METHOD_REFERENCE -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.shared.gms.fingerprints.CertificateFingerprint.indexOfGetPackageNameInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * Method which the package name is used to check the app signature. */ -internal object CertificateFingerprint : ReferenceFingerprint( +internal object CertificateFingerprint : MethodFingerprint( returnType = "Ljava/lang/String;", accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL, parameters = emptyList(), strings = listOf("X.509", "user", "S"), - reference = { GET_PACKAGE_NAME_METHOD_REFERENCE } + customFingerprint = { methodDef, _ -> + indexOfGetPackageNameInstruction(methodDef) >= 0 + } ) { - const val GET_PACKAGE_NAME_METHOD_REFERENCE = - "Landroid/content/Context;->getPackageName()Ljava/lang/String;" + fun indexOfGetPackageNameInstruction(methodDef: Method) = + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Landroid/content/Context;->getPackageName()Ljava/lang/String;" + } } diff --git a/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt index 545556945..5536ceaec 100644 --- a/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt @@ -16,9 +16,9 @@ import app.revanced.patches.shared.litho.fingerprints.ByteBufferFingerprint import app.revanced.patches.shared.litho.fingerprints.EmptyComponentsFingerprint import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -127,7 +127,7 @@ object LithoFilterPatch : BytecodePatch( val stringBuilderRegister = getInstruction(stringBuilderIndex).registerA - val emptyStringIndex = getStringInstructionIndex("") + val emptyStringIndex = indexOfFirstStringInstructionOrThrow("") val identifierRegister = getInstruction( indexOfFirstInstructionReversedOrThrow(emptyStringIndex) { opcode == Opcode.IPUT_OBJECT diff --git a/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt b/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt index 02e3c8135..e34e5d56f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/mainactivity/BaseMainActivityResolvePatch.kt @@ -7,7 +7,7 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import kotlin.properties.Delegates @@ -38,7 +38,8 @@ abstract class BaseMainActivityResolvePatch( // set onBackPressed method onBackPressedMethod = getMethod("onBackPressed") - onBackPressedMethodIndex = onBackPressedMethod.getTargetIndexOrThrow(Opcode.RETURN_VOID) + onBackPressedMethodIndex = + onBackPressedMethod.indexOfFirstInstructionOrThrow(Opcode.RETURN_VOID) // set onConfigurationChanged method onConfigurationChangedMethod = getMethod("onConfigurationChanged") diff --git a/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt index 6a8984cf2..8344971ad 100644 --- a/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/opus/BaseOpusCodecsPatch.kt @@ -7,11 +7,13 @@ import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.opus.fingerprints.CodecReferenceFingerprint import app.revanced.patches.shared.opus.fingerprints.CodecSelectorFingerprint -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This patch is generally not required for the latest versions of YouTube and YouTube Music. @@ -25,15 +27,14 @@ abstract class BaseOpusCodecsPatch( CodecSelectorFingerprint ) ) { - private lateinit var opusCodecReference: Reference - override fun execute(context: BytecodeContext) { - CodecReferenceFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val targetIndex = getTargetIndexWithReferenceOrThrow("Ljava/util/Set;") - opusCodecReference = getInstruction(targetIndex).reference + val opusCodecReference = with(CodecReferenceFingerprint.resultOrThrow().mutableMethod) { + val codecIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.returnType == "Ljava/util/Set;" } + getInstruction(codecIndex).reference } CodecSelectorFingerprint.resultOrThrow().let { diff --git a/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt b/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt index 3ed3ba57c..d6a487dfb 100644 --- a/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/settingmenu/SettingsMenuPatch.kt @@ -8,9 +8,11 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.shared.integrations.Constants.PATCHES_PATH import app.revanced.patches.shared.settingmenu.fingerprints.SettingsMenuFingerprint import app.revanced.patches.shared.viewgroup.ViewGroupMarginLayoutParamsHookPatch -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Patch( description = "Hide the settings menu for YouTube or YouTube Music.", @@ -25,8 +27,9 @@ object SettingsMenuPatch : BytecodePatch( override fun execute(context: BytecodeContext) { SettingsMenuFingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Landroid/support/v7/widget/RecyclerView;") + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Landroid/support/v7/widget/RecyclerView;" + } val insertRegister = getInstruction(insertIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt index 9bcca0159..c8254ad5f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/spoofappversion/BaseSpoofAppVersionPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint.indexOfReleaseInstruction -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction @@ -20,7 +20,8 @@ abstract class BaseSpoofAppVersionPatch( CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().mutableMethod.apply { val versionIndex = indexOfReleaseInstruction(this) + 1 - val insertIndex = getTargetIndexReversedOrThrow(versionIndex, Opcode.IPUT_OBJECT) + val insertIndex = + indexOfFirstInstructionReversedOrThrow(versionIndex, Opcode.IPUT_OBJECT) val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt index 1edafb0b1..e747815bf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ads/general/fingerprints/ShowDialogCommandFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.ads.general.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SlidingDialogAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode internal object ShowDialogCommandFingerprint : MethodFingerprint( @@ -16,7 +16,7 @@ internal object ShowDialogCommandFingerprint : MethodFingerprint( // 18.43 and earlier has a different first parameter. // Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures. customFingerprint = custom@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(SlidingDialogAnimation)) { + if (!methodDef.containsWideLiteralInstructionValue(SlidingDialogAnimation)) { return@custom false } // 18.43 and earlier parameters are: "L", "L" diff --git a/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt index 0e513c8f7..9207a4fab 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt @@ -33,11 +33,10 @@ import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CaptionToggleContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceName -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -113,8 +112,8 @@ object FeedComponentsPatch : BaseBytecodePatch( // region patch for hide caption button CaptionsButtonFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(CaptionToggleContainer) - val insertIndex = getTargetIndexReversedOrThrow(constIndex, Opcode.IF_EQZ) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(CaptionToggleContainer) + val insertIndex = indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.IF_EQZ) val insertRegister = getInstruction(insertIndex).registerA addInstructions( @@ -126,8 +125,8 @@ object FeedComponentsPatch : BaseBytecodePatch( } CaptionsButtonSyntheticFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(CaptionToggleContainer) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(CaptionToggleContainer) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -198,7 +197,7 @@ object FeedComponentsPatch : BaseBytecodePatch( && reference.returnType.startsWith("L") } - val objectIndex = getTargetIndexOrThrow(Opcode.MOVE_OBJECT) + val objectIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_OBJECT) val objectRegister = getInstruction(objectIndex).registerA val jumpIndex = it.scanResult.patternScanResult!!.startIndex @@ -253,7 +252,9 @@ object FeedComponentsPatch : BaseBytecodePatch( ChannelTabRendererFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val iteratorIndex = getTargetIndexWithMethodReferenceName("hasNext") + val iteratorIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "hasNext" + } val iteratorRegister = getInstruction(iteratorIndex).registerC @@ -265,7 +266,8 @@ object FeedComponentsPatch : BaseBytecodePatch( && reference.parameterTypes == channelTabBuilderMethod.parameterTypes } - val objectIndex = getTargetIndexReversedOrThrow(targetIndex, Opcode.IGET_OBJECT) + val objectIndex = + indexOfFirstInstructionReversedOrThrow(targetIndex, Opcode.IGET_OBJECT) val objectInstruction = getInstruction(objectIndex) val objectReference = getInstruction(objectIndex).reference diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt index bfa0c5270..a5a087b43 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/audiotracks/AudioTracksPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patches.youtube.general.audiotracks.fingerprints.StreamingMo import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow @@ -15,6 +15,7 @@ import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object AudioTracksPatch : BaseBytecodePatch( @@ -32,15 +33,14 @@ object AudioTracksPatch : BaseBytecodePatch( opcode == Opcode.CHECK_CAST && (this as ReferenceInstruction).reference.toString() == "Lcom/google/android/libraries/youtube/innertube/model/media/FormatStreamModel;" } - val arrayListIndex = getTargetIndexWithReferenceOrThrow( - formatStreamModelIndex, - "Ljava/util/List;->add(Ljava/lang/Object;)Z" - ) - val insertIndex = - getTargetIndexWithReferenceOrThrow( - arrayListIndex, - "Ljava/util/List;->isEmpty()Z" - ) + 2 + val arrayListIndex = indexOfFirstInstructionOrThrow(formatStreamModelIndex) { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.toString() == "Ljava/util/List;->add(Ljava/lang/Object;)Z" + } + val insertIndex = indexOfFirstInstructionOrThrow(arrayListIndex) { + opcode == Opcode.INVOKE_INTERFACE && + getReference()?.toString() == "Ljava/util/List;->isEmpty()Z" + } + 2 val formatStreamModelRegister = getInstruction(formatStreamModelIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt index 297c3a878..dded8f631 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt @@ -27,9 +27,9 @@ import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_D import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AccountSwitcherAccessibility import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceName -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -37,6 +37,7 @@ 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.util.MethodUtil @Suppress("unused") @@ -171,10 +172,13 @@ object LayoutComponentsPatch : BaseBytecodePatch( AccountSwitcherAccessibilityLabelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AccountSwitcherAccessibility) - val insertIndex = getTargetIndexOrThrow(constIndex, Opcode.IF_EQZ) - val setVisibilityIndex = - getTargetIndexWithMethodReferenceName(insertIndex, "setVisibility") + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(AccountSwitcherAccessibility) + val insertIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.IF_EQZ) + val setVisibilityIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val visibilityRegister = getInstruction(setVisibilityIndex).registerD @@ -209,8 +213,8 @@ object LayoutComponentsPatch : BaseBytecodePatch( // region patch for hide tooltip content TooltipContentFullscreenFingerprint.resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(45384061) - val targetIndex = getTargetIndexOrThrow(literalIndex, Opcode.MOVE_RESULT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45384061) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt index 9b38b5f04..f4c8c6139 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/layoutswitch/LayoutSwitchPatch.kt @@ -10,8 +10,7 @@ import app.revanced.patches.youtube.general.layoutswitch.fingerprints.LayoutSwit import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -34,7 +33,7 @@ object LayoutSwitchPatch : BaseBytecodePatch( GetFormFactorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val jumpIndex = getTargetIndexReversedOrThrow(Opcode.SGET_OBJECT) + val jumpIndex = indexOfFirstInstructionReversedOrThrow(Opcode.SGET_OBJECT) addInstructionsWithLabels( 0, """ @@ -56,7 +55,7 @@ object LayoutSwitchPatch : BaseBytecodePatch( LayoutSwitchFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IF_NEZ) + val insertIndex = indexOfFirstInstructionReversedOrThrow(Opcode.IF_NEZ) val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt index b6d844a46..2bb8182cb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/loadingscreen/GradientLoadingScreenPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patches.youtube.general.loadingscreen.fingerprints.GradientL import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch @Suppress("unused") @@ -29,7 +29,7 @@ object GradientLoadingScreenPatch : BaseBytecodePatch( GradientLoadingScreenPrimaryFingerprint to 45412406, GradientLoadingScreenSecondaryFingerprint to 45418917 ).forEach { (fingerprint, literal) -> - fingerprint.literalInstructionBooleanHook( + fingerprint.injectLiteralInstructionBooleanCall( literal, "$GENERAL_CLASS_DESCRIPTOR->enableGradientLoadingScreen()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt index b5a2529db..8482e06f7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/MiniplayerPatch.kt @@ -44,8 +44,8 @@ import app.revanced.util.fingerprint.LiteralValueFingerprint import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.indexOfWideLiteralInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags @@ -170,7 +170,7 @@ object MiniplayerPatch : BaseBytecodePatch( } if (SettingsPatch.upward1925) { - MiniplayerModernEnabledFingerprint.literalInstructionBooleanHook( + MiniplayerModernEnabledFingerprint.injectLiteralInstructionBooleanCall( 45622882, "$INTEGRATIONS_CLASS_DESCRIPTOR->getModernMiniplayerOverride(Z)Z" ) @@ -181,11 +181,11 @@ object MiniplayerPatch : BaseBytecodePatch( // region Enable double tap action. if (SettingsPatch.upward1925) { - MiniplayerModernConstructorFingerprint.literalInstructionBooleanHook( + MiniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( 45628823, "$INTEGRATIONS_CLASS_DESCRIPTOR->enableMiniplayerDoubleTapAction()Z" ) - MiniplayerModernConstructorFingerprint.literalInstructionBooleanHook( + MiniplayerModernConstructorFingerprint.injectLiteralInstructionBooleanCall( 45630429, "$INTEGRATIONS_CLASS_DESCRIPTOR->getModernMiniplayerOverride(Z)Z" ) @@ -211,7 +211,8 @@ object MiniplayerPatch : BaseBytecodePatch( YtOutlinePictureInPictureWhite to YtOutlineXWhite, YtOutlineXWhite to YtOutlinePictureInPictureWhite, ).forEach { (originalResource, replacementResource) -> - val imageResourceIndex = indexOfWideLiteralInstructionOrThrow(originalResource) + val imageResourceIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(originalResource) val register = getInstruction(imageResourceIndex).registerA @@ -321,7 +322,7 @@ object MiniplayerPatch : BaseBytecodePatch( // region Enable drag and drop. if (SettingsPatch.upward1923) { - MiniplayerModernDragAndDropFingerprint.literalInstructionBooleanHook( + MiniplayerModernDragAndDropFingerprint.injectLiteralInstructionBooleanCall( 45628752, "$INTEGRATIONS_CLASS_DESCRIPTOR->enableMiniplayerDragAndDrop()Z" ) @@ -388,7 +389,7 @@ object MiniplayerPatch : BaseBytecodePatch( ) { resultOrThrow().mutableMethod.apply { val imageViewIndex = indexOfFirstInstructionOrThrow( - indexOfWideLiteralInstructionOrThrow(literalValue) + indexOfFirstWideLiteralInstructionValueOrThrow(literalValue) ) { opcode == Opcode.CHECK_CAST && getReference()?.type == hookedClassType } diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt index 47b8480c3..eba01fd68 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/miniplayer/fingerprints/MiniplayerModernConstructorFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.general.miniplayer.fingerprints.MiniplayerModernConstructorFingerprint.constructorMethodCount import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.util.MethodUtil @@ -13,7 +13,7 @@ internal object MiniplayerModernConstructorFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, parameters = listOf("L"), customFingerprint = custom@{ methodDef, classDef -> - if (!methodDef.containsWideLiteralInstructionIndex(45623000)) // Magic number found in the constructor. + if (!methodDef.containsWideLiteralInstructionValue(45623000)) // Magic number found in the constructor. return@custom false classDef.methods.forEach { @@ -24,8 +24,8 @@ internal object MiniplayerModernConstructorFingerprint : MethodFingerprint( return@custom true // Double tap action (Used in YouTube 19.25.39+). - methodDef.containsWideLiteralInstructionIndex(45628823) - && methodDef.containsWideLiteralInstructionIndex(45630429) + methodDef.containsWideLiteralInstructionValue(45628823) + && methodDef.containsWideLiteralInstructionValue(45630429) } ) { private var constructorMethodCount = 0 diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt index 51d27430c..20376d1a5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/navigation/NavigationBarComponentsPatch.kt @@ -13,13 +13,16 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.navigation.NavigationBarHookPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode 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.reference.MethodReference @Suppress("unused") object NavigationBarComponentsPatch : BaseBytecodePatch( @@ -48,7 +51,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( // region patch for enable translucent navigation bar if (SettingsPatch.upward1923) { - TranslucentNavigationBarFingerprint.literalInstructionBooleanHook( + TranslucentNavigationBarFingerprint.injectLiteralInstructionBooleanCall( 45630927, "$GENERAL_CLASS_DESCRIPTOR->enableTranslucentNavigationBar()Z" ) @@ -85,7 +88,7 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( AutoMotiveFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("Android Automotive") - 1 + val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1 val register = getInstruction(insertIndex).registerA addInstructions( @@ -103,7 +106,10 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( PivotBarSetTextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } val targetRegister = getInstruction(targetIndex).registerC addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt index 59d0ec246..bc421d1c6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/SplashAnimationFingerprint.kt @@ -2,13 +2,13 @@ package app.revanced.patches.youtube.general.splashanimation.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkSplashAnimation -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object SplashAnimationFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Landroid/os/Bundle;"), customFingerprint = { methodDef, _ -> methodDef.name == "onCreate" - && methodDef.containsWideLiteralInstructionIndex(DarkSplashAnimation) + && methodDef.containsWideLiteralInstructionValue(DarkSplashAnimation) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt index c986eb741..339a27ecf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/splashanimation/fingerprints/StartUpResourceIdFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.general.splashanimation.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object StartUpResourceIdFingerprint : MethodFingerprint( @@ -10,7 +10,7 @@ internal object StartUpResourceIdFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, parameters = listOf("I"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(3) - && methodDef.containsWideLiteralInstructionIndex(4) + methodDef.containsWideLiteralInstructionValue(3) + && methodDef.containsWideLiteralInstructionValue(4) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt index acc992511..e68cf7155 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt @@ -39,16 +39,16 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.patches.youtube.utils.toolbar.ToolBarHookPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT +import app.revanced.util.alsoResolve import app.revanced.util.doRecursively -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getTargetIndexWithReferenceReversedOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionHook +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.replaceLiteralInstructionCall import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus import com.android.tools.smali.dexlib2.Opcode @@ -106,7 +106,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( YtPremiumWordMarkHeader, YtWordMarkHeader ).forEach { literal -> - context.literalInstructionHook(literal, smaliInstruction) + context.replaceLiteralInstructionCall(literal, smaliInstruction) } // YouTube's headers have the form of AttributeSet, which is decoded from YouTube's built-in classes. @@ -125,13 +125,11 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ) // The sidebar's header is lithoView. Add a listener to change it. - DrawerContentViewFingerprint.resolve( - context, - DrawerContentViewConstructorFingerprint.resultOrThrow().classDef - ) - DrawerContentViewFingerprint.resultOrThrow().let { + DrawerContentViewFingerprint.alsoResolve( + context, DrawerContentViewConstructorFingerprint + ).let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val insertIndex = DrawerContentViewFingerprint.indexOfAddViewInstruction(this) val insertRegister = getInstruction(insertIndex).registerD addInstruction( @@ -147,7 +145,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( setActionBarRingoMutableClass.methods.first { method -> MethodUtil.isConstructor(method) }.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IPUT_BOOLEAN) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_BOOLEAN) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -172,7 +170,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ActionBarRingoBackgroundFingerprint.resultOrThrow().let { ActionBarRingoTextFingerprint.resolve(context, it.classDef) it.mutableMethod.apply { - val viewIndex = getWideLiteralInstructionIndex(ActionBarRingoBackground) + 2 + val viewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ActionBarRingoBackground) + 2 val viewRegister = getInstruction(viewIndex).registerA addInstructions( @@ -281,16 +280,16 @@ object ToolBarComponentsPatch : BaseBytecodePatch( CreateSearchSuggestionsFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val relativeIndex = getWideLiteralInstructionIndex(40) - val replaceIndex = getTargetIndexWithReferenceReversedOrThrow( - relativeIndex, - "Landroid/widget/ImageView;->setVisibility(I)V" - ) - 1 + val relativeIndex = indexOfFirstWideLiteralInstructionValueOrThrow(40) + val replaceIndex = indexOfFirstInstructionReversedOrThrow(relativeIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.toString() == "Landroid/widget/ImageView;->setVisibility(I)V" + } - 1 - val jumpIndex = getTargetIndexWithReferenceOrThrow( - relativeIndex, - "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" - ) + 4 + val jumpIndex = indexOfFirstInstructionOrThrow(relativeIndex) { + opcode == Opcode.INVOKE_STATIC && + getReference()?.toString() == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" + } + 4 val replaceIndexInstruction = getInstruction(replaceIndex) val replaceIndexReference = @@ -313,7 +312,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button if (SettingsPatch.upward1928) { - ImageSearchButtonConfigFingerprint.literalInstructionBooleanHook( + ImageSearchButtonConfigFingerprint.injectLiteralInstructionBooleanCall( 45617544, "$GENERAL_CLASS_DESCRIPTOR->hideImageSearchButton(Z)Z" ) @@ -327,15 +326,15 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for hide voice search button - SearchBarFingerprint.resolve( - context, - SearchBarParentFingerprint.resultOrThrow().classDef - ) - SearchBarFingerprint.resultOrThrow().let { + SearchBarFingerprint.alsoResolve( + context, SearchBarParentFingerprint + ).let { it.mutableMethod.apply { val startIndex = it.scanResult.patternScanResult!!.startIndex - val setVisibilityIndex = - getTargetIndexWithMethodReferenceNameOrThrow(startIndex, "setVisibility") + val setVisibilityIndex = indexOfFirstInstructionOrThrow(startIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setVisibility" + } val setVisibilityInstruction = getInstruction(setVisibilityIndex) @@ -349,12 +348,11 @@ object ToolBarComponentsPatch : BaseBytecodePatch( SearchResultFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val startIndex = getWideLiteralInstructionIndex(VoiceSearch) - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow( - startIndex, - "setOnClickListener" - ) + val startIndex = indexOfFirstWideLiteralInstructionValueOrThrow(VoiceSearch) + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow(startIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val viewRegister = getInstruction(setOnClickListenerIndex).registerC @@ -370,7 +368,7 @@ object ToolBarComponentsPatch : BaseBytecodePatch( // region patch for replace create button CreateButtonDrawableFingerprint.resultOrThrow().mutableMethod.apply { - val index = getWideLiteralInstructionIndex(YtOutlineVideoCamera) + val index = indexOfFirstWideLiteralInstructionValueOrThrow(YtOutlineVideoCamera) val register = getInstruction(index).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt index 4288d5714..fd04fadfb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/ActionBarRingoBackgroundFingerprint.kt @@ -3,7 +3,7 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.general.toolbar.fingerprints.ActionBarRingoBackgroundFingerprint.indexOfStaticInstruction import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarRingoBackground -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode @@ -13,7 +13,7 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference internal object ActionBarRingoBackgroundFingerprint : MethodFingerprint( returnType = "Landroid/view/View;", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ActionBarRingoBackground) && + methodDef.containsWideLiteralInstructionValue(ActionBarRingoBackground) && indexOfStaticInstruction(methodDef) >= 0 } ) { diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt index 789f2b197..afda22c8d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/DrawerContentViewFingerprint.kt @@ -1,9 +1,14 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.general.toolbar.fingerprints.DrawerContentViewFingerprint.indexOfAddViewInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object DrawerContentViewFingerprint : MethodReferenceNameFingerprint( +internal object DrawerContentViewFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("L"), opcodes = listOf( @@ -12,5 +17,13 @@ internal object DrawerContentViewFingerprint : MethodReferenceNameFingerprint( Opcode.NEW_INSTANCE, Opcode.INVOKE_DIRECT, ), - reference = { "addView" } -) + customFingerprint = { methodDef, _ -> + indexOfAddViewInstruction(methodDef) >= 0 + } +) { + fun indexOfAddViewInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt index fd8eed5bb..facbc289b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/fingerprints/SearchBarFingerprint.kt @@ -1,9 +1,12 @@ package app.revanced.patches.youtube.general.toolbar.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -object SearchBarFingerprint : MethodReferenceNameFingerprint( +object SearchBarFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Ljava/lang/String;"), opcodes = listOf( @@ -12,5 +15,9 @@ object SearchBarFingerprint : MethodReferenceNameFingerprint( Opcode.IGET_BOOLEAN, Opcode.IF_EQZ ), - reference = { "isEmpty" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "isEmpty" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/translations/TranslationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/translations/TranslationsPatch.kt index a3234c46d..3eda299e5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/translations/TranslationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/translations/TranslationsPatch.kt @@ -17,8 +17,24 @@ object TranslationsPatch : BaseResourcePatch( ) { // Array of supported translations, each represented by its language code. private val TRANSLATIONS = arrayOf( - "ar", "bg-rBG", "de-rDE", "el-rGR", "es-rES", "fr-rFR", "hu-rHU", "it-rIT", "ja-rJP", "ko-rKR", - "pl-rPL", "pt-rBR", "ru-rRU", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW" + "ar", + "bg-rBG", + "de-rDE", + "el-rGR", + "es-rES", + "fr-rFR", + "hu-rHU", + "it-rIT", + "ja-rJP", + "ko-rKR", + "pl-rPL", + "pt-rBR", + "ru-rRU", + "tr-rTR", + "uk-rUA", + "vi-rVN", + "zh-rCN", + "zh-rTW" ) private var CustomTranslations by stringPatchOption( diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt index 31cabcf15..e5b70601c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/visual/VisualPreferencesIconsPatch.kt @@ -144,7 +144,8 @@ object VisualPreferencesIconsPatch : BaseResourcePatch( else -> null } if (drawableName == EMPTY_ICON && - ApplyToAll == false) return@loop + ApplyToAll == false + ) return@loop drawableName?.let { node.setAttribute("android:icon", "@drawable/$it") diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt index 0846f8970..676f2caef 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/OpenLinksDirectlyPatch.kt @@ -8,10 +8,13 @@ import app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints.OpenLink import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object OpenLinksDirectlyPatch : BaseBytecodePatch( @@ -32,7 +35,10 @@ object OpenLinksDirectlyPatch : BaseBytecodePatch( ).forEach { fingerprint -> fingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("parse") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.name == "parse" + } val insertRegister = getInstruction(insertIndex).registerC diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt index 58ec1dfb5..1e762dc4c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/share/ShareSheetPatch.kt @@ -13,8 +13,8 @@ import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetRecyclerView import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -46,8 +46,8 @@ object ShareSheetPatch : BaseBytecodePatch( // Detects that the Share sheet panel has been invoked. BottomSheetRecyclerViewFingerprint.resultOrThrow().mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(BottomSheetRecyclerView) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(BottomSheetRecyclerView) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt index f0c43fd8d..0e4475e9b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/ambientmode/AmbientModeSwitchPatch.kt @@ -10,10 +10,10 @@ import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveMod import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -46,12 +46,12 @@ object AmbientModeSwitchPatch : BaseBytecodePatch( ).forEach { (fingerprint, reversed) -> fingerprint.resultOrThrow().mutableMethod.apply { val stringIndex = - getStringInstructionIndex("android.os.action.POWER_SAVE_MODE_CHANGED") + indexOfFirstStringInstructionOrThrow("android.os.action.POWER_SAVE_MODE_CHANGED") val targetIndex = if (reversed) - getTargetIndexReversedOrThrow(stringIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.INVOKE_DIRECT) else - getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_DIRECT) val targetClass = (getInstruction(targetIndex).reference as MethodReference).definingClass @@ -87,7 +87,7 @@ object AmbientModeSwitchPatch : BaseBytecodePatch( // region patch for disable ambient mode in fullscreen - AmbientModeInFullscreenFingerprint.literalInstructionBooleanHook( + AmbientModeInFullscreenFingerprint.injectLiteralInstructionBooleanCall( 45389368, "$PLAYER_CLASS_DESCRIPTOR->disableAmbientModeInFullscreen()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt index 81888b98b..922deb2b7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/PlayerButtonsPatch.kt @@ -24,8 +24,8 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullS import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerCollapseButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -63,9 +63,10 @@ object PlayerButtonsPatch : BaseBytecodePatch( LayoutConstructorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AutoNavToggle) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AutoNavToggle) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( constIndex, """ @@ -124,9 +125,9 @@ object PlayerButtonsPatch : BaseBytecodePatch( // region patch for hide collapse button TitleAnchorFingerprint.resultOrThrow().mutableMethod.apply { - val titleAnchorConstIndex = getWideLiteralInstructionIndex(TitleAnchor) + val titleAnchorConstIndex = indexOfFirstWideLiteralInstructionValueOrThrow(TitleAnchor) val titleAnchorIndex = - getTargetIndexOrThrow(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT) + indexOfFirstInstructionOrThrow(titleAnchorConstIndex, Opcode.MOVE_RESULT_OBJECT) val titleAnchorRegister = getInstruction(titleAnchorIndex).registerA @@ -136,9 +137,9 @@ object PlayerButtonsPatch : BaseBytecodePatch( ) val playerCollapseButtonConstIndex = - getWideLiteralInstructionIndex(PlayerCollapseButton) + indexOfFirstWideLiteralInstructionValueOrThrow(PlayerCollapseButton) val playerCollapseButtonIndex = - getTargetIndexOrThrow(playerCollapseButtonConstIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionOrThrow(playerCollapseButtonConstIndex, Opcode.CHECK_CAST) val playerCollapseButtonRegister = getInstruction(playerCollapseButtonIndex).registerA @@ -159,7 +160,7 @@ object PlayerButtonsPatch : BaseBytecodePatch( (instruction.value as? WideLiteralInstruction)?.wideLiteral == FullScreenButton } val constIndex = buttonCalls.elementAt(buttonCalls.size - 1).index - val castIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val castIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertIndex = castIndex + 1 val insertRegister = getInstruction(castIndex).registerA @@ -180,7 +181,7 @@ object PlayerButtonsPatch : BaseBytecodePatch( PlayerControlsVisibilityModelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val callIndex = getTargetIndexOrThrow(Opcode.INVOKE_DIRECT_RANGE) + val callIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_DIRECT_RANGE) val callInstruction = getInstruction(callIndex) val hasNextParameterRegister = callInstruction.startRegister + HAS_NEXT diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt index 42acc32f1..09e41630f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/FullScreenButtonFingerprint.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.CfFullscreenButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FadeDurationFast import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenButton -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object FullScreenButtonFingerprint : MethodFingerprint( @@ -13,10 +13,10 @@ internal object FullScreenButtonFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Landroid/view/View;"), customFingerprint = handler@{ methodDef, _ -> - if (!methodDef.containsWideLiteralInstructionIndex(FullScreenButton)) + if (!methodDef.containsWideLiteralInstructionValue(FullScreenButton)) return@handler false - methodDef.containsWideLiteralInstructionIndex(FadeDurationFast) // YouTube 18.29.38 ~ YouTube 19.18.41 - || methodDef.containsWideLiteralInstructionIndex(CfFullscreenButton) // YouTube 19.19.39 ~ + methodDef.containsWideLiteralInstructionValue(FadeDurationFast) // YouTube 18.29.38 ~ YouTube 19.18.41 + || methodDef.containsWideLiteralInstructionValue(CfFullscreenButton) // YouTube 19.19.39 ~ }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt index 263e4264d..a6c5b2eaa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/buttons/fingerprints/TitleAnchorFingerprint.kt @@ -3,12 +3,12 @@ package app.revanced.patches.youtube.player.buttons.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.PlayerCollapseButton import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TitleAnchor -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object TitleAnchorFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(PlayerCollapseButton) - && methodDef.containsWideLiteralInstructionIndex(TitleAnchor) + methodDef.containsWideLiteralInstructionValue(PlayerCollapseButton) + && methodDef.containsWideLiteralInstructionValue(TitleAnchor) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt index 132063250..8add5c0f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/comments/CommentsComponentPatch.kt @@ -12,9 +12,9 @@ import app.revanced.patches.youtube.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -56,14 +56,15 @@ object CommentsComponentPatch : BaseBytecodePatch( ShortsLiveStreamEmojiPickerOnClickListenerFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val emojiPickerEndpointIndex = getWideLiteralInstructionIndex(126326492) + val emojiPickerEndpointIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(126326492) val emojiPickerOnClickListenerIndex = - getTargetIndexOrThrow(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT) + indexOfFirstInstructionOrThrow(emojiPickerEndpointIndex, Opcode.INVOKE_DIRECT) val emojiPickerOnClickListenerMethod = getWalkerMethod(context, emojiPickerOnClickListenerIndex) emojiPickerOnClickListenerMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IF_EQZ) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IF_EQZ) val insertRegister = getInstruction(insertIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index 454c38629..6deb71687 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -48,11 +48,11 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBl import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -61,6 +61,7 @@ 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.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object PlayerComponentsPatch : BaseBytecodePatch( @@ -107,8 +108,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ScrimOverlay) - val targetIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ScrimOverlay) + val targetIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val targetParameter = getInstruction(targetIndex).reference val targetRegister = getInstruction(targetIndex).registerA @@ -144,7 +145,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( if (fingerprint == StartVideoInformerFingerprint) { hookInitVideoPanel(1) } else { - val syntheticIndex = getTargetIndexOrThrow(Opcode.NEW_INSTANCE) + val syntheticIndex = + indexOfFirstInstructionOrThrow(opcode = Opcode.NEW_INSTANCE) val syntheticReference = getInstruction(syntheticIndex).reference.toString() val syntheticClass = @@ -228,7 +230,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( DarkBackground, TapBloomView ).forEach { literal -> - QuickSeekOverlayFingerprint.literalInstructionViewHook( + QuickSeekOverlayFingerprint.injectLiteralInstructionViewCall( literal, smaliInstruction ) @@ -273,10 +275,10 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(FadeDurationFast) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(FadeDurationFast) val constRegister = getInstruction(constIndex).registerA val insertIndex = - getTargetIndexReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 + indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.INVOKE_VIRTUAL) + 1 val jumpIndex = implementation!!.instructions.let { instruction -> insertIndex + instruction.subList(insertIndex, instruction.size - 1) .indexOfFirst { instructions -> @@ -341,11 +343,14 @@ object PlayerComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(SeekUndoEduOverlayStub) + val insertIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(SeekUndoEduOverlayStub) val insertRegister = getInstruction(insertIndex).registerA - val onClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow(insertIndex, "setOnClickListener") + val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val constComponent = getConstComponent(insertIndex, onClickListenerIndex - 1) if (constComponent.isNotEmpty()) { @@ -390,8 +395,10 @@ object PlayerComponentsPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.parameters == listOf("Landroid/view/View${'$'}OnClickListener;") }?.apply { - val setOnClickListenerIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setOnClickListener") + val setOnClickListenerIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } val setOnClickListenerRegister = getInstruction(setOnClickListenerIndex).registerC diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt index b07040639..1b7cb1ffa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/components/fingerprints/QuickSeekOverlayFingerprint.kt @@ -3,13 +3,13 @@ package app.revanced.patches.youtube.player.components.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.DarkBackground import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TapBloomView -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object QuickSeekOverlayFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(DarkBackground) - && methodDef.containsWideLiteralInstructionIndex(TapBloomView) + methodDef.containsWideLiteralInstructionValue(DarkBackground) + && methodDef.containsWideLiteralInstructionValue(TapBloomView) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt index 3ef3d2681..c16e31639 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/DescriptionComponentsPatch.kt @@ -20,10 +20,14 @@ import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.recyclerview.BottomSheetRecyclerViewPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object DescriptionComponentsPatch : BaseBytecodePatch( @@ -54,23 +58,23 @@ object DescriptionComponentsPatch : BaseBytecodePatch( // In order to maintain compatibility with YouTube v18.48.39 or previous versions, // This patch is applied only to the version after YouTube v18.49.37. if (SettingsPatch.upward1849) { - RollingNumberTextViewAnimationUpdateFingerprint.resolve( - context, - RollingNumberTextViewFingerprint.resultOrThrow().classDef - ) - RollingNumberTextViewAnimationUpdateFingerprint.resultOrThrow().let { + RollingNumberTextViewAnimationUpdateFingerprint.alsoResolve( + context, RollingNumberTextViewFingerprint + ).let { it.mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 2 val imageSpanIndex = it.scanResult.patternScanResult!!.startIndex - val setTextIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") - + val setTextIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setText" + } addInstruction(setTextIndex, "nop") addInstructionsWithLabels( imageSpanIndex, """ - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->disableRollingNumberAnimations()Z - move-result v$freeRegister - if-nez v$freeRegister, :disable_animations - """, ExternalLabel("disable_animations", getInstruction(setTextIndex)) + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->disableRollingNumberAnimations()Z + move-result v$freeRegister + if-nez v$freeRegister, :disable_animations + """, ExternalLabel("disable_animations", getInstruction(setTextIndex)) ) } } @@ -106,13 +110,11 @@ object DescriptionComponentsPatch : BaseBytecodePatch( } } - EngagementPanelTitleFingerprint.resolve( - context, - EngagementPanelTitleParentFingerprint.resultOrThrow().classDef - ) - EngagementPanelTitleFingerprint.resultOrThrow().mutableMethod.apply { - val contentDescriptionIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setContentDescription") + EngagementPanelTitleFingerprint.alsoResolve( + context, EngagementPanelTitleParentFingerprint + ).mutableMethod.apply { + val contentDescriptionIndex = EngagementPanelTitleFingerprint + .indexOfContentDescriptionInstruction(this) val contentDescriptionRegister = getInstruction(contentDescriptionIndex).registerD diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt index 723f7803e..4fee2997d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/descriptions/fingerprints/EngagementPanelTitleFingerprint.kt @@ -1,8 +1,22 @@ package app.revanced.patches.youtube.player.descriptions.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.player.descriptions.fingerprints.EngagementPanelTitleFingerprint.indexOfContentDescriptionInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object EngagementPanelTitleFingerprint : MethodReferenceNameFingerprint( +internal object EngagementPanelTitleFingerprint : MethodFingerprint( strings = listOf(". "), - reference = { "setContentDescription" } -) \ No newline at end of file + customFingerprint = { methodDef, _ -> + indexOfContentDescriptionInstruction(methodDef) >= 0 + } +) { + fun indexOfContentDescriptionInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setContentDescription" + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt index 6688bbcae..5b48b2606 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/PlayerFlyoutMenuPatch.kt @@ -16,12 +16,15 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetFooterText import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object PlayerFlyoutMenuPatch : BaseBytecodePatch( @@ -56,7 +59,7 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( val smaliInstruction = """ invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $PLAYER_CLASS_DESCRIPTOR->$name(Landroid/view/View;)V """ - fingerprint.literalInstructionViewHook(BottomSheetFooterText, smaliInstruction) + fingerprint.injectLiteralInstructionViewCall(BottomSheetFooterText, smaliInstruction) } arrayOf( @@ -64,15 +67,17 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( QualityMenuViewInflateFingerprint ).forEach { fingerprint -> fingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addHeaderView") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addHeaderView" + } val insertRegister = getInstruction(insertIndex).registerD addInstructions( - insertIndex, - """ - invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hidePlayerFlyoutMenuQualityHeader(Landroid/view/View;)Landroid/view/View; - move-result-object v$insertRegister - """ + insertIndex, """ + invoke-static {v$insertRegister}, $PLAYER_CLASS_DESCRIPTOR->hidePlayerFlyoutMenuQualityHeader(Landroid/view/View;)Landroid/view/View; + move-result-object v$insertRegister + """ ) } } @@ -95,7 +100,7 @@ object PlayerFlyoutMenuPatch : BaseBytecodePatch( SettingsPatch.updatePatchStatus(this) if (SettingsPatch.upward1839) { - PiPModeConfigFingerprint.literalInstructionBooleanHook( + PiPModeConfigFingerprint.injectLiteralInstructionBooleanCall( 45427407, "$PLAYER_CLASS_DESCRIPTOR->hidePiPModeMenu(Z)Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt index 5a1cbf5c5..4c086f4a2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/hide/fingerprints/CaptionsBottomSheetFingerprint.kt @@ -4,13 +4,13 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.BottomSheetFooterText import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SubtitleMenuSettingsFooterInfo -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object CaptionsBottomSheetFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(BottomSheetFooterText) - && methodDef.containsWideLiteralInstructionIndex(SubtitleMenuSettingsFooterInfo) + methodDef.containsWideLiteralInstructionValue(BottomSheetFooterText) + && methodDef.containsWideLiteralInstructionValue(SubtitleMenuSettingsFooterInfo) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt index 9140067b6..3a2d60ae2 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/flyoutmenu/toggle/ChangeTogglePatch.kt @@ -17,11 +17,10 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -139,13 +138,15 @@ object ChangeTogglePatch : BaseBytecodePatch( } val classRegister = getInstruction(iGetIndex).registerB - val stringIndex = getStringInstructionIndex("menu_item_cinematic_lighting") + val stringIndex = + indexOfFirstStringInstructionOrThrow("menu_item_cinematic_lighting") - val checkCastIndex = getTargetIndexReversedOrThrow(stringIndex, Opcode.CHECK_CAST) + val checkCastIndex = + indexOfFirstInstructionReversedOrThrow(stringIndex, Opcode.CHECK_CAST) val iGetObjectPrimaryIndex = - getTargetIndexReversedOrThrow(checkCastIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(checkCastIndex, Opcode.IGET_OBJECT) val iGetObjectSecondaryIndex = - getTargetIndexOrThrow(checkCastIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionOrThrow(checkCastIndex, Opcode.IGET_OBJECT) val checkCastReference = getInstruction(checkCastIndex).reference @@ -154,14 +155,15 @@ object ChangeTogglePatch : BaseBytecodePatch( val iGetObjectSecondaryReference = getInstruction(iGetObjectSecondaryIndex).reference - val invokeVirtualIndex = getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_VIRTUAL) + val invokeVirtualIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_VIRTUAL) val invokeVirtualInstruction = getInstruction(invokeVirtualIndex) val freeRegisterC = invokeVirtualInstruction.registerC val freeRegisterD = invokeVirtualInstruction.registerD val freeRegisterE = invokeVirtualInstruction.registerE - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.RETURN_VOID) + val insertIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.RETURN_VOID) addInstructionsWithLabels( insertIndex, """ diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt index 8a7be9a31..852fab2a1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt @@ -30,12 +30,10 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullS import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.QuickActionsElementContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus @@ -80,8 +78,9 @@ object FullscreenComponentsPatch : BaseBytecodePatch( EngagementPanelFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(FullScreenEngagementPanel) - val targetIndex = getTargetIndexOrThrow(literalIndex, Opcode.CHECK_CAST) + val literalIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(FullScreenEngagementPanel) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(targetIndex).registerA addInstruction( @@ -94,7 +93,10 @@ object FullscreenComponentsPatch : BaseBytecodePatch( PlayerTitleViewFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("addView") + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addView" + } val insertReference = getInstruction(insertIndex).reference.toString() if (!insertReference.startsWith("Landroid/widget/FrameLayout;")) @@ -115,9 +117,10 @@ object FullscreenComponentsPatch : BaseBytecodePatch( LayoutConstructorFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(AutoNavPreviewStub) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(AutoNavPreviewStub) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 + val jumpIndex = + indexOfFirstInstructionOrThrow(constIndex + 2, Opcode.INVOKE_VIRTUAL) + 1 addInstructionsWithLabels( constIndex, """ @@ -159,7 +162,7 @@ object FullscreenComponentsPatch : BaseBytecodePatch( } val constIndex = containerCalls.elementAt(containerCalls.size - 1).index - val checkCastIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val checkCastIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertRegister = getInstruction(checkCastIndex).registerA @@ -183,9 +186,11 @@ object FullscreenComponentsPatch : BaseBytecodePatch( YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = - getTargetIndexWithMethodReferenceNameOrThrow("setFocusableInTouchMode") - val walkerIndex = getTargetIndexOrThrow(targetIndex, Opcode.INVOKE_STATIC) + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setFocusableInTouchMode" + } + val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.INVOKE_STATIC) val walkerMethod = getWalkerMethod(context, walkerIndex) walkerMethod.apply { @@ -209,14 +214,14 @@ object FullscreenComponentsPatch : BaseBytecodePatch( ClientSettingEndpointFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val getActivityIndex = getStringInstructionIndex("watch") + 2 + val getActivityIndex = indexOfFirstStringInstructionOrThrow("watch") + 2 val getActivityReference = getInstruction(getActivityIndex).reference val classRegister = getInstruction(getActivityIndex).registerB val watchDescriptorMethodIndex = - getStringInstructionIndex("start_watch_minimized") - 1 + indexOfFirstStringInstructionOrThrow("start_watch_minimized") - 1 val watchDescriptorRegister = getInstruction(watchDescriptorMethodIndex).registerD @@ -228,7 +233,7 @@ object FullscreenComponentsPatch : BaseBytecodePatch( ) // hooks Activity. - val insertIndex = getStringInstructionIndex("force_fullscreen") + val insertIndex = indexOfFirstStringInstructionOrThrow("force_fullscreen") val freeRegister = getInstruction(insertIndex).registerA addInstructions( @@ -244,9 +249,10 @@ object FullscreenComponentsPatch : BaseBytecodePatch( VideoPortraitParentFingerprint.resultOrThrow().let { it.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("Acquiring NetLatencyActionLogger failed. taskId=") - val invokeIndex = getTargetIndexOrThrow(stringIndex, Opcode.INVOKE_INTERFACE) - val targetIndex = getTargetIndexOrThrow(invokeIndex, Opcode.CHECK_CAST) + indexOfFirstStringInstructionOrThrow("Acquiring NetLatencyActionLogger failed. taskId=") + val invokeIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_INTERFACE) + val targetIndex = indexOfFirstInstructionOrThrow(invokeIndex, Opcode.CHECK_CAST) val targetClass = context .findClass(getInstruction(targetIndex).reference.toString())!! .mutableClass @@ -328,8 +334,9 @@ object FullscreenComponentsPatch : BaseBytecodePatch( BroadcastReceiverFingerprint.resultOrThrow().let { result -> result.mutableMethod.apply { val stringIndex = - getStringInstructionIndex("android.intent.action.SCREEN_ON") - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.IF_EQZ) + 1 + indexOfFirstStringInstructionOrThrow("android.intent.action.SCREEN_ON") + val insertIndex = + indexOfFirstInstructionOrThrow(stringIndex, Opcode.IF_EQZ) + 1 addInstruction( insertIndex, diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt index c1568aef0..2712908f8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/hapticfeedback/HapticFeedBackPatch.kt @@ -13,7 +13,7 @@ import app.revanced.patches.youtube.player.hapticfeedback.fingerprints.ZoomHapti import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -65,7 +65,7 @@ object HapticFeedBackPatch : BaseBytecodePatch( var register = 0 if (name == "run") { - index = getTargetIndexOrThrow(Opcode.SGET) + index = indexOfFirstInstructionOrThrow(Opcode.SGET) register = getInstruction(index).registerA } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt index 17265a15d..3c454136e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/seekbar/SeekbarComponentsPatch.kt @@ -30,11 +30,11 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelT import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -44,6 +44,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import org.w3c.dom.Element @Suppress("DEPRECATION", "unused") @@ -139,11 +140,14 @@ object SeekbarComponentsPatch : BaseBytecodePatch( TotalTimeFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val charSequenceIndex = - getTargetIndexWithMethodReferenceNameOrThrow("getString") + 1 + val charSequenceIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getString" + } + 1 val charSequenceRegister = getInstruction(charSequenceIndex).registerA - val textViewIndex = getTargetIndexWithMethodReferenceNameOrThrow("getText") + val textViewIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getText" + } val textViewRegister = getInstruction(textViewIndex).registerC @@ -162,12 +166,12 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for seekbar color PlayerSeekbarColorFingerprint.resultOrThrow().mutableMethod.apply { - hook(getWideLiteralInstructionIndex(InlineTimeBarColorizedBarPlayedColorDark) + 2) - hook(getWideLiteralInstructionIndex(InlineTimeBarPlayedNotHighlightedColor) + 2) + hook(InlineTimeBarColorizedBarPlayedColorDark) + hook(InlineTimeBarPlayedNotHighlightedColor) } ShortsSeekbarColorFingerprint.resultOrThrow().mutableMethod.apply { - hook(getWideLiteralInstructionIndex(ReelTimeBarPlayedColor) + 2) + hook(ReelTimeBarPlayedColor) } ControlsOverlayStyleFingerprint.resultOrThrow().let { @@ -212,7 +216,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( PlayerButtonsVisibilityFingerprint.resultOrThrow().let { it.mutableMethod.apply { val freeRegister = implementation!!.registerCount - parameters.size - 2 - val viewIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val viewIndex = indexOfFirstInstructionOrThrow(Opcode.INVOKE_INTERFACE) val viewRegister = getInstruction(viewIndex).registerD addInstructionsWithLabels( @@ -271,7 +275,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for restore old seekbar thumbnails ThumbnailPreviewConfigFingerprint.result?.let { - ThumbnailPreviewConfigFingerprint.literalInstructionBooleanHook( + ThumbnailPreviewConfigFingerprint.injectLiteralInstructionBooleanCall( 45398577, "$PLAYER_CLASS_DESCRIPTOR->restoreOldSeekbarThumbnails()Z" ) @@ -285,7 +289,7 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // region patch for enable cairo seekbar if (SettingsPatch.upward1923) { - CairoSeekbarConfigFingerprint.literalInstructionBooleanHook( + CairoSeekbarConfigFingerprint.injectLiteralInstructionBooleanCall( 45617850, "$PLAYER_CLASS_DESCRIPTOR->enableCairoSeekbar()Z" ) @@ -303,7 +307,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch( SettingsPatch.updatePatchStatus(this) } - private fun MutableMethod.hook(insertIndex: Int) { + private fun MutableMethod.hook(literal: Long) { + val insertIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + 2 val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt index 2c6f1ef1b..d4de67d25 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/SpeedOverlayPatch.kt @@ -15,18 +15,15 @@ import app.revanced.patches.youtube.player.speedoverlay.fingerprints.NextGenWatc import app.revanced.patches.youtube.player.speedoverlay.fingerprints.RestoreSlideToSeekBehaviorFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SlideToSeekMotionEventFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayFingerprint +import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayFloatValueFingerprint import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayTextValueFingerprint -import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverlayValueFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.alsoResolve import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow -import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -35,6 +32,8 @@ 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.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil @Patch(dependencies = [SharedResourceIdPatch::class]) object SpeedOverlayPatch : BytecodePatch( @@ -43,8 +42,8 @@ object SpeedOverlayPatch : BytecodePatch( NextGenWatchLayoutFingerprint, RestoreSlideToSeekBehaviorFingerprint, SpeedOverlayFingerprint, + SpeedOverlayFloatValueFingerprint, SpeedOverlayTextValueFingerprint, - SpeedOverlayValueFingerprint, ) ) { override fun execute(context: BytecodeContext) { @@ -52,36 +51,33 @@ object SpeedOverlayPatch : BytecodePatch( val restoreSlideToSeekBehaviorFingerprintResult = RestoreSlideToSeekBehaviorFingerprint.result val speedOverlayFingerprintResult = SpeedOverlayFingerprint.result - val speedOverlayValueFingerprintResult = SpeedOverlayValueFingerprint.result + val speedOverlayFloatValueFingerprintResult = SpeedOverlayFloatValueFingerprint.result val resolvable = restoreSlideToSeekBehaviorFingerprintResult != null && speedOverlayFingerprintResult != null - && speedOverlayValueFingerprintResult != null + && speedOverlayFloatValueFingerprintResult != null if (resolvable) { - // Legacy method. // Used on YouTube 18.29.38 ~ YouTube 19.17.41 - // region patch for disable speed overlay + // region patch for Disable speed overlay (Enable slide to seek) mapOf( RestoreSlideToSeekBehaviorFingerprint to 45411329, SpeedOverlayFingerprint to 45411330 ).forEach { (fingerprint, literal) -> - fingerprint.result!!.let { - fingerprint.literalInstructionBooleanHook( - literal, - "$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z" - ) - } + fingerprint.injectLiteralInstructionBooleanCall( + literal, + "$PLAYER_CLASS_DESCRIPTOR->disableSpeedOverlay(Z)Z" + ) } // endregion - // region patch for custom speed overlay value + // region patch for Custom speed overlay float value - speedOverlayValueFingerprintResult!!.let { + speedOverlayFloatValueFingerprintResult!!.let { it.mutableMethod.apply { val index = it.scanResult.patternScanResult!!.startIndex val register = getInstruction(index).registerA @@ -98,13 +94,18 @@ object SpeedOverlayPatch : BytecodePatch( // endregion } else { - // New method. // Used on YouTube 19.18.41~ - NextGenWatchLayoutFingerprint.resultOrThrow().mutableMethod.apply { - val booleanValueIndex = getTargetIndexWithMethodReferenceNameOrThrow("booleanValue") + // region patch for Disable speed overlay (Enable slide to seek) - val insertIndex = findIGetIndex(booleanValueIndex - 10, booleanValueIndex) + NextGenWatchLayoutFingerprint.resultOrThrow().mutableMethod.apply { + val booleanValueIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "booleanValue" + } + val insertIndex = indexOfFirstInstructionOrThrow(booleanValueIndex - 10) { + opcode == Opcode.IGET_OBJECT + && getReference()?.definingClass == definingClass + } val insertInstruction = getInstruction(insertIndex) val insertReference = getInstruction(insertIndex).reference @@ -113,77 +114,107 @@ object SpeedOverlayPatch : BytecodePatch( "iget-object v${insertInstruction.registerA}, v${insertInstruction.registerB}, $insertReference" ) - val jumpIndex = findIGetIndex(booleanValueIndex, booleanValueIndex + 10) + val jumpIndex = indexOfFirstInstructionOrThrow(booleanValueIndex) { + opcode == Opcode.IGET_OBJECT + && getReference()?.definingClass == definingClass + } hook(insertIndex + 1, insertInstruction.registerA, jumpIndex) } - SlideToSeekMotionEventFingerprint.resolve( - context, - HorizontalTouchOffsetConstructorFingerprint.resultOrThrow().classDef - ) - SlideToSeekMotionEventFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val scanResult = it.scanResult.patternScanResult!! + val (slideToSeekBooleanMethod, slideToSeekSyntheticMethod) = + SlideToSeekMotionEventFingerprint.alsoResolve( + context, HorizontalTouchOffsetConstructorFingerprint + ).let { + with(it.mutableMethod) { + val scanResult = it.scanResult.patternScanResult!! + val jumpIndex = scanResult.endIndex + 1 + val insertIndex = scanResult.endIndex - 1 + val insertRegister = + getInstruction(insertIndex).registerA - val slideToSeekBooleanIndex = scanResult.startIndex + 1 - slideToSeekBooleanMethod = getWalkerMethod(context, slideToSeekBooleanIndex) - - val jumpIndex = scanResult.endIndex + 1 - val insertIndex = scanResult.endIndex - 1 - val insertRegister = - getInstruction(insertIndex).registerA - - hook(insertIndex, insertRegister, jumpIndex) - } - } - - slideToSeekBooleanMethod.apply { - var insertIndex = getTargetIndexOrThrow(Opcode.IGET_OBJECT) - var insertRegister = getInstruction(insertIndex).registerA - var jumpIndex = getTargetIndexReversedOrThrow(Opcode.INVOKE_VIRTUAL) - - hook(insertIndex, insertRegister, jumpIndex) - - val constructorMethod = - context.findClass(definingClass)?.mutableClass - ?.methods?.find { method -> method.name == "" } - ?: throw PatchException("Could not find constructor method") - - constructorMethod.apply { - val syntheticIndex = getTargetIndexReversedOrThrow(Opcode.NEW_INSTANCE) - val syntheticClass = - getInstruction(syntheticIndex).reference.toString() - - val syntheticMethod = - context.findClass(syntheticClass)?.mutableClass - ?.methods?.find { method -> method.name == "run" } - ?: throw PatchException("Could not find synthetic method") - - syntheticMethod.apply { - val speedOverlayValueIndex = - indexOfFirstInstructionOrThrow { (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() } - val speedOverlayValueRegister = - getInstruction(speedOverlayValueIndex).registerA - - addInstructions( - speedOverlayValueIndex + 1, """ - invoke-static {v$speedOverlayValueRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F - move-result v$speedOverlayValueRegister - """ - ) - - insertIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow( - speedOverlayValueIndex, - "removeCallbacks" - ) + 1 - insertRegister = - getInstruction(insertIndex - 1).registerC - jumpIndex = - getTargetIndexOrThrow(speedOverlayValueIndex, Opcode.RETURN_VOID) + 1 hook(insertIndex, insertRegister, jumpIndex) + + val slideToSeekBooleanMethod = context.toMethodWalker(it.mutableMethod) + .nextMethod(scanResult.startIndex + 1, true) + .getMethod() as MutableMethod + + val slideToSeekConstructorMethod = + context.findClass { classDef -> classDef.type == slideToSeekBooleanMethod.definingClass } + ?.mutableClass + ?.methods + ?.find { method -> MethodUtil.isConstructor(method) } + ?: throw PatchException("Could not find constructor method") + + val slideToSeekSyntheticIndex = slideToSeekConstructorMethod + .indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.NEW_INSTANCE + } + + val slideToSeekSyntheticClass = slideToSeekConstructorMethod + .getInstruction(slideToSeekSyntheticIndex) + .reference + .toString() + + val slideToSeekSyntheticMethod = + context.findClass { classDef -> classDef.type == slideToSeekSyntheticClass } + ?.mutableClass + ?.methods + ?.find { method -> method.name == "run" } + ?: throw PatchException("Could not find synthetic method") + + Pair(slideToSeekBooleanMethod, slideToSeekSyntheticMethod) } } + + slideToSeekBooleanMethod.apply { + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.IGET_OBJECT + } + val insertRegister = getInstruction(insertIndex).registerA + val jumpIndex = indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.INVOKE_VIRTUAL + } + + hook(insertIndex, insertRegister, jumpIndex) + } + + slideToSeekSyntheticMethod.apply { + val speedOverlayFloatValueIndex = indexOfFirstInstructionOrThrow { + (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() + } + val insertIndex = + indexOfFirstInstructionReversedOrThrow(speedOverlayFloatValueIndex) { + getReference()?.name == "removeCallbacks" + } + 1 + val insertRegister = + getInstruction(insertIndex - 1).registerC + val jumpIndex = + indexOfFirstInstructionOrThrow( + speedOverlayFloatValueIndex, + Opcode.RETURN_VOID + ) + 1 + + hook(insertIndex, insertRegister, jumpIndex) + } + + // endregion + + // region patch for Custom speed overlay float value + + slideToSeekSyntheticMethod.apply { + val speedOverlayFloatValueIndex = indexOfFirstInstructionOrThrow { + (this as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() + } + val speedOverlayFloatValueRegister = + getInstruction(speedOverlayFloatValueIndex).registerA + + addInstructions( + speedOverlayFloatValueIndex + 1, """ + invoke-static {v$speedOverlayFloatValueRegister}, $PLAYER_CLASS_DESCRIPTOR->speedOverlayValue(F)F + move-result v$speedOverlayFloatValueRegister + """ + ) } SpeedOverlayTextValueFingerprint.resultOrThrow().let { @@ -200,11 +231,12 @@ object SpeedOverlayPatch : BytecodePatch( ) } } + + // endregion + } } - private lateinit var slideToSeekBooleanMethod: MutableMethod - // restore slide to seek private fun MutableMethod.hook( insertIndex: Int, @@ -220,14 +252,4 @@ object SpeedOverlayPatch : BytecodePatch( """, ExternalLabel("disable", getInstruction(jumpIndex)) ) } - - private fun MutableMethod.findIGetIndex( - startIndex: Int, - endIndex: Int - ): Int = implementation!!.instructions.let { instruction -> - startIndex + instruction.subList(startIndex, endIndex).indexOfFirst { - it.opcode == Opcode.IGET_OBJECT - && it.getReference()?.definingClass == definingClass - } - } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt index f5ef60b0c..4e54b4a7e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/NextGenWatchLayoutFingerprint.kt @@ -2,8 +2,10 @@ package app.revanced.patches.youtube.player.speedoverlay.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsMethodReferenceNameInstructionIndex +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.reference.MethodReference internal object NextGenWatchLayoutFingerprint : MethodFingerprint( returnType = "Z", @@ -13,6 +15,8 @@ internal object NextGenWatchLayoutFingerprint : MethodFingerprint( if (methodDef.definingClass != "Lcom/google/android/apps/youtube/app/watch/nextgenwatch/ui/NextGenWatchLayout;") return@handler false - methodDef.containsMethodReferenceNameInstructionIndex("booleanValue") + methodDef.indexOfFirstInstruction { + getReference()?.name == "booleanValue" + } >= 0 } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt index e27dac2f0..a6904c670 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/RestoreSlideToSeekBehaviorFingerprint.kt @@ -5,6 +5,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value restores the 'Slide to seek' behavior. + * Deprecated in YouTube v19.18.41+. */ internal object RestoreSlideToSeekBehaviorFingerprint : LiteralValueFingerprint( returnType = "Z", diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt index dd1fc9e7e..ad71e2e0d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFingerprint.kt @@ -5,6 +5,7 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value disables 'Playing at 2x speed' while holding down. + * Deprecated in YouTube v19.18.41+. */ internal object SpeedOverlayFingerprint : LiteralValueFingerprint( returnType = "Z", diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt similarity index 81% rename from src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt index c60dc03f8..d5557db6b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayFloatValueFingerprint.kt @@ -7,8 +7,9 @@ import com.android.tools.smali.dexlib2.Opcode /** * This value is the key for the playback speed overlay value. + * Deprecated in YouTube v19.18.41+. */ -internal object SpeedOverlayValueFingerprint : LiteralValueFingerprint( +internal object SpeedOverlayFloatValueFingerprint : LiteralValueFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, opcodes = listOf(Opcode.DOUBLE_TO_FLOAT), diff --git a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt index 434305547..53de379db 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/player/speedoverlay/fingerprints/SpeedOverlayTextValueFingerprint.kt @@ -1,14 +1,21 @@ package app.revanced.patches.youtube.player.speedoverlay.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object SpeedOverlayTextValueFingerprint : ReferenceFingerprint( +internal object SpeedOverlayTextValueFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = emptyList(), opcodes = listOf(Opcode.CONST_WIDE_HIGH16), - reference = { "Ljava/math/BigDecimal;->signum()I" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Ljava/math/BigDecimal;->signum()I" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt index 153517b64..118a6eac0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsAnimationPatch.kt @@ -15,8 +15,8 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelF import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.util.ResourceGroup import app.revanced.util.copyResources -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -38,7 +38,7 @@ object ShortsAnimationPatch : BytecodePatch( ReelFeedbackPause to "setShortsPauseFeedback", ReelFeedbackPlay to "setShortsPlayFeedback", ).forEach { (literal, methodName) -> - val literalIndex = getWideLiteralInstructionIndex(literal) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) val viewIndex = indexOfFirstInstructionOrThrow(literalIndex) { opcode == Opcode.CHECK_CAST && (this as? ReferenceInstruction)?.reference?.toString() == LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt index a213ff0f0..e30dac5c8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsComponentPatch.kt @@ -35,12 +35,12 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Right import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionHook +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.patch.BaseBytecodePatch +import app.revanced.util.replaceLiteralInstructionCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -48,6 +48,7 @@ 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.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") object ShortsComponentPatch : BaseBytecodePatch( @@ -106,10 +107,11 @@ object ShortsComponentPatch : BaseBytecodePatch( ShortsButtonFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(ReelRightDislikeIcon) + val constIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelRightDislikeIcon) val constRegister = getInstruction(constIndex).registerA - val jumpIndex = getTargetIndexOrThrow(constIndex, Opcode.CONST_CLASS) + 2 + val jumpIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CONST_CLASS) + 2 addInstructionsWithLabels( constIndex + 1, """ @@ -128,9 +130,9 @@ object ShortsComponentPatch : BaseBytecodePatch( ShortsButtonFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getWideLiteralInstructionIndex(ReelRightLikeIcon) + val insertIndex = indexOfFirstWideLiteralInstructionValueOrThrow(ReelRightLikeIcon) val insertRegister = getInstruction(insertIndex).registerA - val jumpIndex = getTargetIndexOrThrow(insertIndex, Opcode.CONST_CLASS) + 2 + val jumpIndex = indexOfFirstInstructionOrThrow(insertIndex, Opcode.CONST_CLASS) + 2 addInstructionsWithLabels( insertIndex + 1, """ @@ -152,11 +154,12 @@ object ShortsComponentPatch : BaseBytecodePatch( if (shortsPivotLegacyFingerprintResult != null) { // Legacy method. shortsPivotLegacyFingerprintResult.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(ReelForcedMuteButton) + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelForcedMuteButton) val targetRegister = getInstruction(targetIndex).registerA - val insertIndex = getTargetIndexReversedOrThrow(targetIndex, Opcode.IF_EQZ) - val jumpIndex = getTargetIndexOrThrow(targetIndex, Opcode.GOTO) + val insertIndex = indexOfFirstInstructionReversedOrThrow(targetIndex, Opcode.IF_EQZ) + val jumpIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.GOTO) addInstructionsWithLabels( insertIndex, """ @@ -173,7 +176,7 @@ object ShortsComponentPatch : BaseBytecodePatch( move-result v$REGISTER_TEMPLATE_REPLACEMENT """ - context.literalInstructionHook( + context.replaceLiteralInstructionCall( ReelPlayerRightPivotV2Size, smaliInstruction ) @@ -242,7 +245,8 @@ object ShortsComponentPatch : BaseBytecodePatch( lateinit var subscriptionFieldReference: FieldReference parentResult.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(ReelPlayerFooter) - 1 + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(ReelPlayerFooter) - 1 subscriptionFieldReference = (getInstruction(targetIndex)).reference as FieldReference } @@ -297,9 +301,9 @@ object ShortsComponentPatch : BaseBytecodePatch( TextComponentSpecFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;") - + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;" + } val charSequenceRegister = getInstruction(insertIndex).registerC val conversionContextRegister = @@ -342,11 +346,11 @@ object ShortsComponentPatch : BaseBytecodePatch( ) { resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(id) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(id) val insertIndex = if (reversed) - getTargetIndexReversedOrThrow(constIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionReversedOrThrow(constIndex, Opcode.CHECK_CAST) else - getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -363,8 +367,8 @@ object ShortsComponentPatch : BaseBytecodePatch( ) { resultOrThrow().let { it.mutableMethod.apply { - val constIndex = getWideLiteralInstructionIndex(id) - val insertIndex = getTargetIndexOrThrow(constIndex, Opcode.CHECK_CAST) + val constIndex = indexOfFirstWideLiteralInstructionValueOrThrow(id) + val insertIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.CHECK_CAST) hideButtons(insertIndex, descriptor) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt index 776dd3191..1b91a281b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsNavigationBarPatch.kt @@ -10,10 +10,12 @@ import app.revanced.patches.youtube.shorts.components.fingerprints.RenderBottomN import app.revanced.patches.youtube.shorts.components.fingerprints.SetPivotBarFingerprint import app.revanced.patches.youtube.utils.fingerprints.InitializeButtonsFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference object ShortsNavigationBarPatch : BytecodePatch( setOf( @@ -51,7 +53,9 @@ object ShortsNavigationBarPatch : BytecodePatch( BottomNavigationBarFingerprint.result?.let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("findViewById") + 1 + val targetIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "findViewById" + } + 1 val insertRegister = getInstruction(targetIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt index b7484a31c..8c16daabb 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsRepeatPatch.kt @@ -9,14 +9,18 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.shorts.components.fingerprints.ReelEnumConstructorFingerprint import app.revanced.patches.youtube.shorts.components.fingerprints.ReelEnumStaticFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.SHORTS_CLASS_DESCRIPTOR -import app.revanced.util.containsReferenceInstructionIndex import app.revanced.util.findMutableMethodOf -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import com.android.tools.smali.dexlib2.util.MethodUtil object ShortsRepeatPatch : BytecodePatch( setOf(ReelEnumConstructorFingerprint) @@ -36,16 +40,15 @@ object ShortsRepeatPatch : BytecodePatch( } val endScreenStringIndex = - getStringInstructionIndex("REEL_LOOP_BEHAVIOR_END_SCREEN") + indexOfFirstStringInstructionOrThrow("REEL_LOOP_BEHAVIOR_END_SCREEN") val endScreenReferenceIndex = - getTargetIndexOrThrow(endScreenStringIndex, Opcode.SPUT_OBJECT) + indexOfFirstInstructionOrThrow(endScreenStringIndex, Opcode.SPUT_OBJECT) val endScreenReference = getInstruction(endScreenReferenceIndex).reference.toString() - val enumMethodName = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod.name - val enumMethodCall = "$definingClass->$enumMethodName(I)$definingClass" + val enumMethod = ReelEnumStaticFingerprint.resultOrThrow().mutableMethod - context.injectHook(endScreenReference, enumMethodCall) + context.injectHook(endScreenReference, enumMethod) } } } @@ -54,8 +57,8 @@ object ShortsRepeatPatch : BytecodePatch( enumName: String, fieldName: String ) { - val stringIndex = getStringInstructionIndex(enumName) - val insertIndex = getTargetIndexOrThrow(stringIndex, Opcode.SPUT_OBJECT) + val stringIndex = indexOfFirstStringInstructionOrThrow(enumName) + val insertIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.SPUT_OBJECT) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -66,35 +69,41 @@ object ShortsRepeatPatch : BytecodePatch( private fun BytecodeContext.injectHook( endScreenReference: String, - enumMethodCall: String + enumMethod: MutableMethod ) { classes.forEach { classDef -> classDef.methods.filter { method -> method.parameters.size == 1 && method.parameters[0].startsWith("L") && method.returnType == "V" - && method.containsReferenceInstructionIndex(endScreenReference) + && method.indexOfFirstInstruction { + getReference()?.toString() == endScreenReference + } >= 0 }.forEach { targetMethod -> proxy(classDef) .mutableClass .findMutableMethodOf(targetMethod) .apply { - for ((index, instruction) in implementation!!.instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_STATIC) - continue - if ((instruction as ReferenceInstruction).reference.toString() != enumMethodCall) - continue + implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + val reference = (instruction as? ReferenceInstruction)?.reference + reference is MethodReference && + MethodUtil.methodSignaturesMatch(enumMethod, reference) + } + .map { (index, _) -> index } + .reversed() + .forEach { index -> + val register = + getInstruction(index + 1).registerA - val register = - getInstruction(index + 1).registerA - - addInstructions( - index + 2, """ - invoke-static {v$register}, $SHORTS_CLASS_DESCRIPTOR->changeShortsRepeatState(Ljava/lang/Enum;)Ljava/lang/Enum; - move-result-object v$register - """ - ) - } + addInstructions( + index + 2, """ + invoke-static {v$register}, $SHORTS_CLASS_DESCRIPTOR->changeShortsRepeatState(Ljava/lang/Enum;)Ljava/lang/Enum; + move-result-object v$register + """ + ) + } } } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt index cf5371223..dfdc55a3f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/ShortsTimeStampPatch.kt @@ -13,9 +13,9 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.MetaP import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelVodTimeStampsContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook -import app.revanced.util.literalInstructionViewHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall +import app.revanced.util.injectLiteralInstructionViewCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -38,14 +38,14 @@ object ShortsTimeStampPatch : BytecodePatch( ShortsTimeStampPrimaryFingerprint to 45638282, ShortsTimeStampSecondaryFingerprint to 45638187 ).forEach { (fingerprint, literal) -> - fingerprint.literalInstructionBooleanHook( + fingerprint.injectLiteralInstructionBooleanCall( literal, "$SHORTS_CLASS_DESCRIPTOR->enableShortsTimeStamp(Z)Z" ) } ShortsTimeStampPrimaryFingerprint.resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(10002) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(10002) val literalRegister = getInstruction(literalIndex).registerA addInstructions( @@ -81,7 +81,7 @@ object ShortsTimeStampPatch : BytecodePatch( invoke-static {v$REGISTER_TEMPLATE_REPLACEMENT}, $SHORTS_CLASS_DESCRIPTOR->$methodName(Landroid/view/View;)V """ - fingerprint.literalInstructionViewHook(literalValue, smaliInstruction) + fingerprint.injectLiteralInstructionViewCall(literalValue, smaliInstruction) } // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt index 901af28bd..5081b1ff5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ReelFeedbackFingerprint.kt @@ -4,13 +4,13 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackLike import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackPause import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelFeedbackPlay -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object ReelFeedbackFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ReelFeedbackLike) - && methodDef.containsWideLiteralInstructionIndex(ReelFeedbackPause) - && methodDef.containsWideLiteralInstructionIndex(ReelFeedbackPlay) + methodDef.containsWideLiteralInstructionValue(ReelFeedbackLike) + && methodDef.containsWideLiteralInstructionValue(ReelFeedbackPause) + && methodDef.containsWideLiteralInstructionValue(ReelFeedbackPlay) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt index 6f7d94c0a..12e5e844c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsButtonFingerprint.kt @@ -6,15 +6,15 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelD import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightDislikeIcon import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ReelRightLikeIcon import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.RightComment -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue internal object ShortsButtonFingerprint : MethodFingerprint( returnType = "V", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ReelDynRemix) - && methodDef.containsWideLiteralInstructionIndex(ReelDynShare) - && methodDef.containsWideLiteralInstructionIndex(ReelRightDislikeIcon) - && methodDef.containsWideLiteralInstructionIndex(ReelRightLikeIcon) - && methodDef.containsWideLiteralInstructionIndex(RightComment) + methodDef.containsWideLiteralInstructionValue(ReelDynRemix) + && methodDef.containsWideLiteralInstructionValue(ReelDynShare) + && methodDef.containsWideLiteralInstructionValue(ReelRightDislikeIcon) + && methodDef.containsWideLiteralInstructionValue(ReelRightLikeIcon) + && methodDef.containsWideLiteralInstructionValue(RightComment) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt index 9e34f0119..d2a2fdfa0 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shorts/components/fingerprints/ShortsTimeStampPrimaryFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.shorts.components.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object ShortsTimeStampPrimaryFingerprint : MethodFingerprint( @@ -10,8 +10,8 @@ internal object ShortsTimeStampPrimaryFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("I"), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(45627350) - && methodDef.containsWideLiteralInstructionIndex(45638282) - && methodDef.containsWideLiteralInstructionIndex(10002) + methodDef.containsWideLiteralInstructionValue(45627350) + && methodDef.containsWideLiteralInstructionValue(45638282) + && methodDef.containsWideLiteralInstructionValue(10002) }, ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt index 686c02dfc..1fcad075e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/swipe/controls/SwipeControlsPatch.kt @@ -23,8 +23,8 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.util.ResourceGroup import app.revanced.util.copyResources -import app.revanced.util.getWideLiteralInstructionIndex -import app.revanced.util.literalInstructionBooleanHook +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.transformMethods @@ -90,7 +90,8 @@ object SwipeControlsPatch : BaseBytecodePatch( FullScreenEngagementOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val viewIndex = getWideLiteralInstructionIndex(FullScreenEngagementOverlay) + 3 + val viewIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(FullScreenEngagementOverlay) + 3 val viewRegister = getInstruction(viewIndex).registerA addInstruction( @@ -131,7 +132,7 @@ object SwipeControlsPatch : BaseBytecodePatch( // Since it does not support all versions, // add settings only if the patch is successful. SwipeToSwitchVideoFingerprint.result?.let { - SwipeToSwitchVideoFingerprint.literalInstructionBooleanHook( + SwipeToSwitchVideoFingerprint.injectLiteralInstructionBooleanCall( 45631116, "$INTEGRATIONS_SWIPE_CONTROLS_PATCH_CLASS_DESCRIPTOR->enableSwipeToSwitchVideo()Z" ) @@ -147,7 +148,7 @@ object SwipeControlsPatch : BaseBytecodePatch( // Since it does not support all versions, // add settings only if the patch is successful. WatchPanelGesturesFingerprint.result?.let { - WatchPanelGesturesFingerprint.literalInstructionBooleanHook( + WatchPanelGesturesFingerprint.injectLiteralInstructionBooleanCall( 45372793, "$INTEGRATIONS_SWIPE_CONTROLS_PATCH_CLASS_DESCRIPTOR->enableWatchPanelGestures()Z" ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt index 6db2ab6bb..39ac28f63 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/CastButtonPatch.kt @@ -17,11 +17,14 @@ import app.revanced.patches.youtube.utils.integrations.Constants.PATCH_STATUS_CL import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus 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.reference.MethodReference @Patch(dependencies = [SharedResourceIdPatch::class]) object CastButtonPatch : BytecodePatch( @@ -39,12 +42,11 @@ object CastButtonPatch : BytecodePatch( override fun execute(context: BytecodeContext) { - val toolbarMenuItemInitializeResult = MenuItemInitializeFingerprint.resultOrThrow() - MenuItemVisibilityFingerprint.resolve(context, toolbarMenuItemInitializeResult.classDef) - - toolbarMenuItemInitializeMethod = toolbarMenuItemInitializeResult.mutableMethod - toolbarMenuItemVisibilityMethod = - MenuItemVisibilityFingerprint.resultOrThrow().mutableMethod + toolbarMenuItemInitializeMethod = MenuItemInitializeFingerprint.resultOrThrow() + .mutableMethod + toolbarMenuItemVisibilityMethod = MenuItemVisibilityFingerprint.alsoResolve( + context, MenuItemInitializeFingerprint + ).mutableMethod playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod @@ -64,7 +66,9 @@ object CastButtonPatch : BytecodePatch( internal fun hookPlayerButton(context: BytecodeContext) { playerButtonMethod.apply { - val index = getTargetIndexWithMethodReferenceNameOrThrow("setVisibility") + val index = indexOfFirstInstructionOrThrow { + getReference()?.name == "setVisibility" + } val instruction = getInstruction(index) val viewRegister = instruction.registerC val visibilityRegister = instruction.registerD @@ -84,8 +88,9 @@ object CastButtonPatch : BytecodePatch( internal fun hookToolBarButton(context: BytecodeContext) { toolbarMenuItemInitializeMethod.apply { - val index = getTargetIndexWithMethodReferenceNameOrThrow("setShowAsAction") + 1 - + val index = indexOfFirstInstructionOrThrow { + getReference()?.name == "setShowAsAction" + } + 1 addInstruction( index, "invoke-static {p1}, $GENERAL_CLASS_DESCRIPTOR->hideCastButton(Landroid/view/MenuItem;)V" diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt index 18e37f62c..a52f69071 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/castbutton/fingerprints/MenuItemVisibilityFingerprint.kt @@ -1,12 +1,19 @@ package app.revanced.patches.youtube.utils.castbutton.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object MenuItemVisibilityFingerprint : MethodReferenceNameFingerprint( +internal object MenuItemVisibilityFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Z"), - reference = { "setVisible" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.name == "setVisible" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt index e14a7ad92..20063ed0e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/PlayerSeekbarColorFingerprint.kt @@ -4,15 +4,15 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InlineTimeBarColorizedBarPlayedColorDark import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InlineTimeBarPlayedNotHighlightedColor -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object PlayerSeekbarColorFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(InlineTimeBarColorizedBarPlayedColorDark) - && methodDef.containsWideLiteralInstructionIndex( + methodDef.containsWideLiteralInstructionValue(InlineTimeBarColorizedBarPlayedColorDark) + && methodDef.containsWideLiteralInstructionValue( InlineTimeBarPlayedNotHighlightedColor ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt index 727b29ced..39a48fb61 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/YouTubeControlsOverlayFingerprint.kt @@ -8,7 +8,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inset import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ScrimOverlay import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.SeekUndoEduOverlayStub import app.revanced.patches.youtube.utils.sponsorblock.SponsorBlockBytecodePatch -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -26,9 +26,9 @@ internal object YouTubeControlsOverlayFingerprint : MethodFingerprint( accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, parameters = emptyList(), customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(FadeDurationFast) - && methodDef.containsWideLiteralInstructionIndex(InsetOverlayViewLayout) - && methodDef.containsWideLiteralInstructionIndex(ScrimOverlay) - && methodDef.containsWideLiteralInstructionIndex(SeekUndoEduOverlayStub) + methodDef.containsWideLiteralInstructionValue(FadeDurationFast) + && methodDef.containsWideLiteralInstructionValue(InsetOverlayViewLayout) + && methodDef.containsWideLiteralInstructionValue(ScrimOverlay) + && methodDef.containsWideLiteralInstructionValue(SeekUndoEduOverlayStub) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt index 2ee24f0a1..66374cddf 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/bottomui/CfBottomUIPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.youtube.utils.fix.bottomui import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.fix.bottomui.fingerprints.FullscreenButtonPositionFingerprint import app.revanced.patches.youtube.utils.fix.bottomui.fingerprints.FullscreenButtonViewStubFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fixes an issue where overlay button patches were broken by the new layout." @@ -32,19 +27,10 @@ object CfBottomUIPatch : BytecodePatch( FullscreenButtonPositionFingerprint to 45627640 ).forEach { (fingerprint, literalValue) -> fingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = getTargetIndexOrThrow( - getWideLiteralInstructionIndex(literalValue.toLong()), - Opcode.MOVE_RESULT - ) - val targetRegister = - getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + fingerprint.injectLiteralInstructionBooleanCall( + literalValue, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt index 74b3ee248..c20fd4a11 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/cairo/CairoSettingsPatch.kt @@ -1,16 +1,11 @@ package app.revanced.patches.youtube.utils.fix.cairo import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.misc.backgroundplayback.BackgroundPlaybackPatch import app.revanced.patches.youtube.utils.fix.cairo.fingerprints.CarioFragmentConfigFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fixes issues where Cairo Fragment is applied." @@ -31,19 +26,10 @@ object CairoSettingsPatch : BytecodePatch( * for screenshots of the Cairo Fragment. */ CarioFragmentConfigFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45532100), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + CarioFragmentConfigFingerprint.injectLiteralInstructionBooleanCall( + 45532100, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt index 60da209b9..9788f3bec 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/shortsplayback/ShortsPlaybackPatch.kt @@ -1,15 +1,10 @@ package app.revanced.patches.youtube.utils.fix.shortsplayback import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.fix.shortsplayback.fingerprints.ShortsPlaybackFingerprint -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getWideLiteralInstructionIndex -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import app.revanced.util.injectLiteralInstructionBooleanCall @Patch( description = "Fix issue with looping at the start of the video when applying default video quality to Shorts." @@ -26,19 +21,10 @@ object ShortsPlaybackPatch : BytecodePatch( * RVX applies default video quality to Shorts as well, so this patch is required. */ ShortsPlaybackFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = - getTargetIndexOrThrow( - getWideLiteralInstructionIndex(45387052), - Opcode.MOVE_RESULT - ) - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x0" - ) - } + ShortsPlaybackFingerprint.injectLiteralInstructionBooleanCall( + 45387052, + "0x0" + ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt index 702185779..a4b297c0b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/SuggestedVideoEndScreenPatch.kt @@ -8,9 +8,9 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.fingerprints.RemoveOnLayoutChangeListenerFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DESCRIPTOR -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.getWalkerMethod +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @@ -36,9 +36,10 @@ object SuggestedVideoEndScreenPatch : BytecodePatch( it.getWalkerMethod(context, it.scanResult.patternScanResult!!.endIndex) walkerIndex.apply { - val invokeInterfaceIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val invokeInterfaceIndex = + indexOfFirstInstructionOrThrow(opcode = Opcode.INVOKE_INTERFACE) val iGetObjectIndex = - getTargetIndexReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(invokeInterfaceIndex, Opcode.IGET_OBJECT) val invokeInterfaceReference = getInstruction(invokeInterfaceIndex).reference diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt index 2c0f744e7..2c923219b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fix/suggestedvideoendscreen/fingerprints/RemoveOnLayoutChangeListenerFingerprint.kt @@ -1,15 +1,18 @@ package app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This fingerprint is also compatible with very old YouTube versions. - * Tested on YouTube v16.40.36, v18.29.38, v19.12.41. + * Tested on YouTube v16.40.36, v18.29.38, v19.16.39. */ -internal object RemoveOnLayoutChangeListenerFingerprint : ReferenceFingerprint( +internal object RemoveOnLayoutChangeListenerFingerprint : MethodFingerprint( returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = emptyList(), @@ -18,5 +21,10 @@ internal object RemoveOnLayoutChangeListenerFingerprint : ReferenceFingerprint( Opcode.INVOKE_VIRTUAL ), // This is the only reference present in the entire smali. - reference = { "YouTubePlayerOverlaysLayout;->removeOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() + ?.endsWith("YouTubePlayerOverlaysLayout;->removeOnLayoutChangeListener(Landroid/view/View${'$'}OnLayoutChangeListener;)V") == true + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt index 324b69131..638c0fa83 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt @@ -16,8 +16,8 @@ import app.revanced.patches.youtube.utils.playercontrols.fingerprints.MotionEven import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityEntityModelFingerprint import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -50,13 +50,11 @@ object PlayerControlsPatch : BytecodePatch( // region patch for hook visibility of play control buttons (e.g. pause, play button, etc) - PlayerButtonsVisibilityFingerprint.resolve( - context, - PlayerButtonsResourcesFingerprint.resultOrThrow().mutableClass - ) - PlayerButtonsVisibilityFingerprint.resultOrThrow().let { + PlayerButtonsVisibilityFingerprint.alsoResolve( + context, PlayerButtonsResourcesFingerprint + ).let { it.mutableMethod.apply { - val viewIndex = getTargetIndexOrThrow(Opcode.INVOKE_INTERFACE) + val viewIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.INVOKE_INTERFACE) val viewRegister = getInstruction(viewIndex).registerD addInstruction( @@ -70,11 +68,9 @@ object PlayerControlsPatch : BytecodePatch( // region patch for hook visibility of play controls layout - PlayerControlsVisibilityFingerprint.resolve( - context, - YouTubeControlsOverlayFingerprint.resultOrThrow().mutableClass - ) - PlayerControlsVisibilityFingerprint.resultOrThrow().mutableMethod.addInstruction( + PlayerControlsVisibilityFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).mutableMethod.addInstruction( 0, "invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->changeVisibility(Z)V" ) @@ -83,12 +79,10 @@ object PlayerControlsPatch : BytecodePatch( // region patch for detecting motion events in play controls layout - MotionEventFingerprint.resolve( - context, - YouTubeControlsOverlayFingerprint.resultOrThrow().mutableClass - ) - MotionEventFingerprint.resultOrThrow().mutableMethod.apply { - val insertIndex = getTargetIndexWithMethodReferenceNameOrThrow("setTranslationY") + 1 + MotionEventFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).mutableMethod.apply { + val insertIndex = MotionEventFingerprint.indexOfTranslationInstruction(this) + 1 addInstruction( insertIndex, diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt index b991ec65c..5f9fd61ff 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsVisibilityHookPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityEntityModelFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @@ -31,7 +31,7 @@ object PlayerControlsVisibilityHookPatch : BytecodePatch( val staticReference = getInstruction(startIndex + 1).reference it.mutableClass.methods.find { method -> method.name == "" }?.apply { - val targetIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) + val targetIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt index 45d9d329d..743129ab4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/fingerprints/MotionEventFingerprint.kt @@ -1,9 +1,21 @@ package app.revanced.patches.youtube.utils.playercontrols.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.playercontrols.fingerprints.MotionEventFingerprint.indexOfTranslationInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object MotionEventFingerprint : MethodReferenceNameFingerprint( +internal object MotionEventFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("Landroid/view/MotionEvent;"), - reference = { "setTranslationY" } -) + customFingerprint = { methodDef, _ -> + indexOfTranslationInstruction(methodDef) >= 0 + } +) { + fun indexOfTranslationInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "setTranslationY" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt index 9f208cdfe..4dc3d749a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/PlayerTypeHookPatch.kt @@ -16,8 +16,8 @@ import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFinge import app.revanced.patches.youtube.utils.playertype.fingerprint.VideoStateFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.util.addFieldAndInstructions -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @@ -82,14 +82,14 @@ object PlayerTypeHookPatch : BytecodePatch( BrowseIdClassFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getStringInstructionIndex("VL") - 1 + val targetIndex = indexOfFirstStringInstructionOrThrow("VL") - 1 val targetReference = getInstruction(targetIndex).reference val targetClass = context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass targetClass.methods.find { method -> method.name == "" } ?.apply { - val browseIdFieldIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) + val browseIdFieldIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) val browseIdFieldName = (getInstruction(browseIdFieldIndex).reference as FieldReference).name diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt index 1a6452a6f..d14e8a9e5 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/playertype/fingerprint/ActionBarSearchResultsFingerprint.kt @@ -4,7 +4,7 @@ import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.playertype.fingerprint.ActionBarSearchResultsFingerprint.indexOfLayoutDirectionInstruction import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.ActionBarSearchResultsViewMic -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.AccessFlags @@ -16,7 +16,7 @@ internal object ActionBarSearchResultsFingerprint : MethodFingerprint( accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "Landroid/view/View;", customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(ActionBarSearchResultsViewMic) && + methodDef.containsWideLiteralInstructionValue(ActionBarSearchResultsViewMic) && indexOfLayoutDirectionInstruction(methodDef) >= 0 } ) { diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt index b04544925..560fd7437 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/recyclerview/BottomSheetRecyclerViewPatch.kt @@ -2,18 +2,16 @@ package app.revanced.patches.youtube.utils.recyclerview import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.recyclerview.fingerprints.BottomSheetRecyclerViewBuilderFingerprint import app.revanced.patches.youtube.utils.recyclerview.fingerprints.RecyclerViewTreeObserverFingerprint import app.revanced.util.getReference -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.injectLiteralInstructionBooleanCall import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference object BottomSheetRecyclerViewPatch : BytecodePatch( @@ -35,15 +33,10 @@ object BottomSheetRecyclerViewPatch : BytecodePatch( * Therefore, we need to force this to be true. */ BottomSheetRecyclerViewBuilderFingerprint.result?.let { - it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(45382015) + 2 - val targetRegister = getInstruction(targetIndex).registerA - - addInstruction( - targetIndex + 1, - "const/4 v$targetRegister, 0x1" - ) - } + BottomSheetRecyclerViewBuilderFingerprint.injectLiteralInstructionBooleanCall( + 45382015, + "0x1" + ) } RecyclerViewTreeObserverFingerprint.resultOrThrow().mutableMethod.apply { @@ -54,7 +47,7 @@ object BottomSheetRecyclerViewPatch : BytecodePatch( && getReference()?.type == "Landroid/view/ViewTreeObserver${'$'}OnDrawListener;" } recyclerViewTreeObserverInsertIndex = - getTargetIndexReversedOrThrow(onDrawListenerIndex, Opcode.CHECK_CAST) + 1 + indexOfFirstInstructionReversedOrThrow(onDrawListenerIndex, Opcode.CHECK_CAST) + 1 } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt index 4095c72af..a580ea3ca 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/general/ReturnYouTubeDislikePatch.kt @@ -20,16 +20,15 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceType -import app.revanced.util.getTargetIndexWithFieldReferenceTypeOrThrow import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") @@ -78,13 +77,15 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch( TextComponentContextFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val conversionContextFieldIndex = - getTargetIndexWithFieldReferenceTypeOrThrow("Ljava/util/Map;") - 1 + val conversionContextFieldIndex = indexOfFirstInstructionOrThrow { + getReference()?.type == "Ljava/util/Map;" + } - 1 val conversionContextFieldReference = getInstruction(conversionContextFieldIndex).reference - val charSequenceIndex1932 = - getTargetIndexWithFieldReferenceType("Ljava/util/BitSet;") - 1 + val charSequenceIndex1932 = indexOfFirstInstruction { + getReference()?.type == "Ljava/util/BitSet;" + } - 1 val charSequenceIndex1933 = indexOfFirstInstruction { val reference = getReference() opcode == Opcode.INVOKE_VIRTUAL && @@ -108,7 +109,7 @@ object ReturnYouTubeDislikePatch : BaseBytecodePatch( } val freeRegister = getInstruction( - getTargetIndexOrThrow(insertIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionOrThrow(insertIndex, Opcode.IGET_OBJECT) ).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt index 29490b004..03931cb73 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/ReturnYouTubeDislikeRollingNumberPatch.kt @@ -17,14 +17,15 @@ import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fin import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureTextParentFingerprint import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberSetterFingerprint import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference @Patch(dependencies = [SettingsPatch::class]) @@ -60,7 +61,8 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( rollingNumberClass.methods.find { method -> method.name == "" } ?.apply { - val rollingNumberFieldIndex = getTargetIndexOrThrow(Opcode.IPUT_OBJECT) + val rollingNumberFieldIndex = + indexOfFirstInstructionOrThrow(opcode = Opcode.IPUT_OBJECT) charSequenceFieldReference = getInstruction(rollingNumberFieldIndex).reference } ?: throw PatchException("RollingNumberClass not found!") @@ -103,7 +105,7 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( """ ) - val ifGeIndex = getTargetIndexOrThrow(Opcode.IF_GE) + val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE) val ifGeInstruction = getInstruction(ifGeIndex) removeInstruction(ifGeIndex) @@ -153,7 +155,9 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( realTimeUpdateTextViewMethod ).forEach { insertMethod -> insertMethod.apply { - val setTextIndex = getTargetIndexWithMethodReferenceNameOrThrow("setText") + val setTextIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "setText" + } val textViewRegister = getInstruction(setTextIndex).registerC val textSpanRegister = diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt index 80ceaec83..a15449332 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/rollingnumber/fingerprints/RollingNumberMeasureAnimatedTextFingerprint.kt @@ -1,12 +1,15 @@ package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints -import app.revanced.util.fingerprint.ReferenceFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** * This fingerprint is compatible with YouTube v18.30.xx+ */ -internal object RollingNumberMeasureAnimatedTextFingerprint : ReferenceFingerprint( +internal object RollingNumberMeasureAnimatedTextFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT, @@ -14,5 +17,9 @@ internal object RollingNumberMeasureAnimatedTextFingerprint : ReferenceFingerpri Opcode.ADD_INT_LIT8, Opcode.GOTO ), - reference = { "Landroid/text/TextPaint;->measureText([CII)F" } + customFingerprint = { methodDef, _ -> + methodDef.indexOfFirstInstruction { + getReference()?.toString() == "Landroid/text/TextPaint;->measureText([CII)F" + } >= 0 + } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt index cdb6c8946..25fd45485 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/returnyoutubedislike/shorts/ReturnYouTubeDislikeShortsPatch.kt @@ -12,14 +12,15 @@ import app.revanced.patches.youtube.utils.fingerprints.TextComponentSpecFingerpr import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.fingerprints.ShortsTextViewFingerprint import app.revanced.patches.youtube.utils.settings.SettingsPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow -import app.revanced.util.getTargetIndexWithReferenceOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.resultOrThrow 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.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch(dependencies = [SettingsPatch::class]) object ReturnYouTubeDislikeShortsPatch : BytecodePatch( @@ -37,9 +38,9 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( val startIndex = it.scanResult.patternScanResult!!.startIndex val isDisLikesBooleanIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.IGET_BOOLEAN) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.IGET_BOOLEAN) val textViewFieldIndex = - getTargetIndexReversedOrThrow(startIndex, Opcode.IGET_OBJECT) + indexOfFirstInstructionReversedOrThrow(startIndex, Opcode.IGET_OBJECT) // If the field is true, the TextView is for a dislike button. val isDisLikesBooleanReference = @@ -51,7 +52,7 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( // Check if the hooked TextView object is that of the dislike button. // If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted. // Otherwise, the TextView object is modified, and the execution flow is interrupted to prevent it from being changed afterward. - val insertIndex = getTargetIndexOrThrow(Opcode.CHECK_CAST) + 1 + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.CHECK_CAST) + 1 addInstructionsWithLabels( insertIndex, """ @@ -73,14 +74,13 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( if (SettingsPatch.upward1834) { TextComponentSpecFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = - getTargetIndexWithReferenceOrThrow("Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;") - + val insertIndex = indexOfFirstInstructionOrThrow { + getReference()?.toString() == "Landroid/text/SpannableString;->valueOf(Ljava/lang/CharSequence;)Landroid/text/SpannableString;" + } val charSequenceRegister = getInstruction(insertIndex).registerC val conversionContextRegister = getInstruction(0).registerA - val replaceReference = getInstruction(insertIndex).reference 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 3012c270e..9bda4f425 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 @@ -19,11 +19,11 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.Inset import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversedOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow -import app.revanced.util.getTargetIndexWithMethodReferenceNameReversedOrThrow -import app.revanced.util.getWideLiteralInstructionIndex +import app.revanced.util.alsoResolve +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus import com.android.tools.smali.dexlib2.Opcode @@ -31,6 +31,7 @@ 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.reference.FieldReference +import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( dependencies = [ @@ -74,13 +75,11 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) } - val seekBarClass = SeekbarFingerprint.resultOrThrow().mutableClass - SeekbarOnDrawFingerprint.resolve(context, seekBarClass) - RectangleFieldInvalidatorFingerprint.resolve(context, seekBarClass) - - SeekbarOnDrawFingerprint.resultOrThrow().mutableMethod.apply { + SeekbarOnDrawFingerprint.alsoResolve( + context, SeekbarFingerprint + ).mutableMethod.apply { // Get left and right of seekbar rectangle - val moveObjectIndex = getTargetIndexOrThrow(Opcode.MOVE_OBJECT_FROM16) + val moveObjectIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.MOVE_OBJECT_FROM16) addInstruction( moveObjectIndex + 1, @@ -89,7 +88,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Set seekbar thickness - val roundIndex = getTargetIndexWithMethodReferenceNameOrThrow("round") + 1 + val roundIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "round" + } + 1 val roundRegister = getInstruction(roundIndex).registerA addInstruction( @@ -99,7 +100,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( ) // Draw segment - val drawCircleIndex = getTargetIndexWithMethodReferenceNameReversedOrThrow("drawCircle") + val drawCircleIndex = indexOfFirstInstructionReversedOrThrow { + getReference()?.name == "drawCircle" + } val drawCircleInstruction = getInstruction(drawCircleIndex) addInstruction( drawCircleIndex, @@ -116,7 +119,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( // Append timestamp TotalTimeFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("getString") + 1 + val targetIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getString" + } + 1 val targetRegister = getInstruction(targetIndex).registerA addInstructions( @@ -131,8 +136,9 @@ object SponsorBlockBytecodePatch : BytecodePatch( // Initialize the SponsorBlock view YouTubeControlsOverlayFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) - val checkCastIndex = getTargetIndexOrThrow(targetIndex, Opcode.CHECK_CAST) + val targetIndex = + indexOfFirstWideLiteralInstructionValueOrThrow(InsetOverlayViewLayout) + val checkCastIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.CHECK_CAST) val targetRegister = getInstruction(checkCastIndex).registerA @@ -144,14 +150,15 @@ object SponsorBlockBytecodePatch : BytecodePatch( } // Replace strings - RectangleFieldInvalidatorFingerprint.resultOrThrow().let { result -> + RectangleFieldInvalidatorFingerprint.alsoResolve( + context, SeekbarFingerprint + ).let { result -> result.mutableMethod.apply { val invalidateIndex = - getTargetIndexWithMethodReferenceNameReversedOrThrow("invalidate") - val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversedOrThrow( - invalidateIndex + 1, - "Landroid/graphics/Rect;" - ) + RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this) + val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } val rectangleFieldName = (getInstruction(rectangleIndex).reference as FieldReference).name 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 598513e7c..89415c67a 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,9 +1,21 @@ package app.revanced.patches.youtube.utils.sponsorblock.fingerprints -import app.revanced.util.fingerprint.MethodReferenceNameFingerprint +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionReversed +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.reference.MethodReference -internal object RectangleFieldInvalidatorFingerprint : MethodReferenceNameFingerprint( +internal object RectangleFieldInvalidatorFingerprint : MethodFingerprint( returnType = "V", parameters = emptyList(), - reference = { "invalidate" } -) + customFingerprint = { methodDef, _ -> + indexOfInvalidateInstruction(methodDef) >= 0 + } +) { + fun indexOfInvalidateInstruction(methodDef: Method) = + methodDef.indexOfFirstInstructionReversed { + getReference()?.name == "invalidate" + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt index b2e2464b6..5012f0c09 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/trackingurlhook/TrackingUrlHookPatch.kt @@ -6,9 +6,12 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.trackingurlhook.fingerprints.TrackingUrlModelFingerprint -import app.revanced.util.getTargetIndexWithMethodReferenceNameOrThrow +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference object TrackingUrlHookPatch : BytecodePatch( setOf(TrackingUrlModelFingerprint) @@ -22,7 +25,10 @@ object TrackingUrlHookPatch : BytecodePatch( internal fun hookTrackingUrl( descriptor: String ) = trackingUrlMethod.apply { - val targetIndex = getTargetIndexWithMethodReferenceNameOrThrow("parse") + 1 + val targetIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC && + getReference()?.name == "parse" + } + 1 val targetRegister = getInstruction(targetIndex).registerA var smaliInstruction = "invoke-static {v$targetRegister}, $descriptor" diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index ddeab2fa5..b647bbb30 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -40,11 +40,10 @@ import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.addFieldAndInstructions import app.revanced.util.alsoResolve import app.revanced.util.getReference -import app.revanced.util.getTargetIndexOrThrow -import app.revanced.util.getTargetIndexReversedOrThrow import app.revanced.util.getWalkerMethod -import app.revanced.util.getWideLiteralInstructionIndex import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstWideLiteralInstructionValueOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -232,9 +231,12 @@ object VideoInformationPatch : BytecodePatch( "videoInformationClass" ) - val literalIndex = getWideLiteralInstructionIndex(45368273) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(45368273) val walkerIndex = - getTargetIndexReversedOrThrow(literalIndex, Opcode.INVOKE_VIRTUAL_RANGE) + indexOfFirstInstructionReversedOrThrow( + literalIndex, + Opcode.INVOKE_VIRTUAL_RANGE + ) videoEndMethod = getWalkerMethod(context, walkerIndex) @@ -364,10 +366,11 @@ object VideoInformationPatch : BytecodePatch( OnPlaybackSpeedItemClickFingerprint.resultOrThrow().let { it.mutableMethod.apply { speedSelectionInsertMethod = this - val speedSelectionValueInstructionIndex = getTargetIndexOrThrow(Opcode.IGET) + val speedSelectionValueInstructionIndex = + indexOfFirstInstructionOrThrow(Opcode.IGET) val setPlaybackSpeedContainerClassFieldIndex = - getTargetIndexReversedOrThrow( + indexOfFirstInstructionReversedOrThrow( speedSelectionValueInstructionIndex, Opcode.IGET_OBJECT ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt index b142dd735..0e419ab53 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/fingerprints/VideoIdFingerprintShorts.kt @@ -2,9 +2,11 @@ package app.revanced.patches.youtube.video.information.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR -import app.revanced.util.containsWideLiteralInstructionIndex -import app.revanced.util.getTargetIndexWithFieldReferenceName +import app.revanced.util.containsWideLiteralInstructionValue +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.reference.FieldReference /** * This fingerprint is compatible with all versions of YouTube starting from v18.29.38 to supported versions. @@ -19,9 +21,11 @@ internal object VideoIdFingerprintShorts : MethodFingerprint( Opcode.MOVE_RESULT_OBJECT ), customFingerprint = custom@{ methodDef, _ -> - if (methodDef.containsWideLiteralInstructionIndex(45365621)) + if (methodDef.containsWideLiteralInstructionValue(45365621)) return@custom true - methodDef.getTargetIndexWithFieldReferenceName("reelWatchEndpoint") >= 0 + methodDef.indexOfFirstInstruction { + getReference()?.name == "reelWatchEndpoint" + } >= 0 } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt index 23edbf025..6a17f77c8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playback/VideoPlaybackPatch.kt @@ -33,10 +33,9 @@ import app.revanced.patches.youtube.video.playback.fingerprints.QualitySetterFin import app.revanced.patches.youtube.video.playback.fingerprints.VP9CapabilityFingerprint import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.getReference -import app.revanced.util.getStringInstructionIndex -import app.revanced.util.getTargetIndexOrThrow import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch import app.revanced.util.resultOrThrow import app.revanced.util.updatePatchStatus @@ -112,7 +111,8 @@ object VideoPlaybackPatch : BaseBytecodePatch( // region patch for disable HDR video HDRCapabilityFingerprint.resultOrThrow().mutableMethod.apply { - val stringIndex = getStringInstructionIndex("av1_profile_main_10_hdr_10_plus_supported") + val stringIndex = + indexOfFirstStringInstructionOrThrow("av1_profile_main_10_hdr_10_plus_supported") val walkerIndex = indexOfFirstInstructionOrThrow(stringIndex) { val reference = getReference() reference?.parameterTypes == listOf("I", "Landroid/view/Display;") @@ -149,7 +149,8 @@ object VideoPlaybackPatch : BaseBytecodePatch( speedSelectionInsertMethod ).forEach { it.apply { - val speedSelectionValueInstructionIndex = getTargetIndexOrThrow(Opcode.IGET) + val speedSelectionValueInstructionIndex = + indexOfFirstInstructionOrThrow(Opcode.IGET) val speedSelectionValueRegister = getInstruction(speedSelectionValueInstructionIndex).registerA @@ -227,7 +228,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( QualityMenuViewInflateFingerprint.resultOrThrow().let { it.mutableMethod.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.CHECK_CAST) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.CHECK_CAST) val insertRegister = getInstruction(insertIndex).registerA addInstruction( @@ -240,7 +241,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableClass.methods.find { method -> method.name == "onItemClick" } onItemClickMethod?.apply { - val insertIndex = getTargetIndexOrThrow(Opcode.IGET_OBJECT) + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.IGET_OBJECT) val insertRegister = getInstruction(insertIndex).registerA val jumpIndex = indexOfFirstInstructionOrThrow { @@ -291,7 +292,7 @@ object VideoPlaybackPatch : BaseBytecodePatch( AV1CodecFingerprint.result?.let { it.mutableMethod.apply { - val insertIndex = getStringInstructionIndex("video/av01") + val insertIndex = indexOfFirstStringInstructionOrThrow("video/av01") val insertRegister = getInstruction(insertIndex).registerA addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt index 30442651b..88e28d7fa 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/playback/fingerprints/AV1CodecFingerprint.kt @@ -2,7 +2,7 @@ package app.revanced.patches.youtube.video.playback.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.AccessFlags internal object AV1CodecFingerprint : MethodFingerprint( @@ -13,6 +13,6 @@ internal object AV1CodecFingerprint : MethodFingerprint( if (methodDef.returnType == "Ljava/util/List;") return@handler false - methodDef.containsWideLiteralInstructionIndex(1987076931) + methodDef.containsWideLiteralInstructionValue(1987076931) } ) diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 702df1930..1065d8ec6 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -25,9 +25,9 @@ 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.WideLiteralInstruction import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i -import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.Reference +import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.util.MethodUtil @@ -96,45 +96,51 @@ fun MutableMethod.injectHideViewCall( "invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V" ) -fun MethodFingerprint.literalInstructionBooleanHook( +fun MethodFingerprint.injectLiteralInstructionBooleanCall( literal: Int, descriptor: String -) = literalInstructionBooleanHook(literal.toLong(), descriptor) +) = injectLiteralInstructionBooleanCall(literal.toLong(), descriptor) -fun MethodFingerprint.literalInstructionBooleanHook( +fun MethodFingerprint.injectLiteralInstructionBooleanCall( literal: Long, descriptor: String ) { resultOrThrow().mutableMethod.apply { - val literalIndex = getWideLiteralInstructionIndex(literal) - val targetIndex = getTargetIndex(literalIndex, Opcode.MOVE_RESULT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT) val targetRegister = getInstruction(targetIndex).registerA - val smaliInstruction = if (descriptor.endsWith("(Z)Z")) - "invoke-static {v$targetRegister}, $descriptor" - else - "invoke-static {}, $descriptor" - - addInstructions( - targetIndex + 1, """ - $smaliInstruction + val smaliInstruction = + if (descriptor.startsWith("0x")) """ + const/16 v$targetRegister, $descriptor + """ + else if (descriptor.endsWith("(Z)Z")) """ + invoke-static {v$targetRegister}, $descriptor move-result v$targetRegister """ + else """ + invoke-static {}, $descriptor + move-result v$targetRegister + """ + + addInstructions( + targetIndex + 1, + smaliInstruction ) } } -fun MethodFingerprint.literalInstructionViewHook( +fun MethodFingerprint.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String -) = resultOrThrow().mutableMethod.literalInstructionViewHook(literal, smaliInstruction) +) = resultOrThrow().mutableMethod.injectLiteralInstructionViewCall(literal, smaliInstruction) -fun MutableMethod.literalInstructionViewHook( +fun MutableMethod.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String ) { - val literalIndex = getWideLiteralInstructionIndex(literal) - val targetIndex = getTargetIndex(literalIndex, Opcode.MOVE_RESULT_OBJECT) + val literalIndex = indexOfFirstWideLiteralInstructionValueOrThrow(literal) + val targetIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.MOVE_RESULT_OBJECT) val targetRegister = getInstruction(targetIndex).registerA.toString() addInstructions( @@ -143,7 +149,7 @@ fun MutableMethod.literalInstructionViewHook( ) } -fun BytecodeContext.literalInstructionViewHook( +fun BytecodeContext.injectLiteralInstructionViewCall( literal: Long, smaliInstruction: String ) { @@ -160,14 +166,14 @@ fun BytecodeContext.literalInstructionViewHook( context.proxy(classDef) .mutableClass .findMutableMethodOf(method) - .literalInstructionViewHook(literal, smaliInstruction) + .injectLiteralInstructionViewCall(literal, smaliInstruction) } } } } } -fun BytecodeContext.literalInstructionHook( +fun BytecodeContext.replaceLiteralInstructionCall( literal: Long, smaliInstruction: String ) { @@ -184,7 +190,7 @@ fun BytecodeContext.literalInstructionHook( context.proxy(classDef) .mutableClass .findMutableMethodOf(method).apply { - val index = getWideLiteralInstructionIndex(literal) + val index = indexOfFirstWideLiteralInstructionValueOrThrow(literal) val register = (instruction as OneRegisterInstruction).registerA.toString() @@ -200,25 +206,17 @@ fun BytecodeContext.literalInstructionHook( } /** - * Get the index of the first instruction with the literal value or throw a [PatchException]. + * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * - * @throws [PatchException] if the literal index not found. + * @param startIndex Optional starting index to start searching from. + * @return -1 if the instruction is not found. + * @see indexOfFirstInstructionOrThrow */ -fun Method.indexOfWideLiteralInstructionOrThrow(literal: Long): Int { - val index = getWideLiteralInstructionIndex(literal) - if (index < 0) { - val value = - if (literal >= 2130706432) // 0x7f000000, general resource id - String.format("%#X", literal).lowercase() - else - literal.toString() - - throw PatchException("Found literal value for: '$value' but method does not contain the id: $this") +fun Method.indexOfFirstInstruction(startIndex: Int = 0, opcode: Opcode): Int = + indexOfFirstInstruction(startIndex) { + this.opcode == opcode } - return index -} - /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -227,7 +225,10 @@ fun Method.indexOfWideLiteralInstructionOrThrow(literal: Long): Int { * @see indexOfFirstInstructionOrThrow */ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.() -> Boolean): Int { - var instructions = this.implementation!!.instructions + if (implementation == null) { + return -1 + } + var instructions = implementation!!.instructions if (startIndex != 0) { instructions = instructions.drop(startIndex) } @@ -240,6 +241,9 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.( } } +fun Method.indexOfFirstInstructionOrThrow(opcode: Opcode): Int = + indexOfFirstInstructionOrThrow(0, opcode) + /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -247,11 +251,14 @@ fun Method.indexOfFirstInstruction(startIndex: Int = 0, predicate: Instruction.( * @throws PatchException * @see indexOfFirstInstruction */ -fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, targetOpcode: Opcode): Int = +fun Method.indexOfFirstInstructionOrThrow(startIndex: Int = 0, opcode: Opcode): Int = indexOfFirstInstructionOrThrow(startIndex) { - opcode == targetOpcode + this.opcode == opcode } +fun Method.indexOfFirstInstructionReversedOrThrow(opcode: Opcode): Int = + indexOfFirstInstructionReversedOrThrow(null, opcode) + /** * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. * @@ -278,9 +285,9 @@ fun Method.indexOfFirstInstructionOrThrow( * @return -1 if the instruction is not found. * @see indexOfFirstInstructionReversedOrThrow */ -fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, targetOpcode: Opcode): Int = +fun Method.indexOfFirstInstructionReversed(startIndex: Int? = null, opcode: Opcode): Int = indexOfFirstInstructionReversed(startIndex) { - opcode == targetOpcode + this.opcode == opcode } /** @@ -295,7 +302,10 @@ fun Method.indexOfFirstInstructionReversed( startIndex: Int? = null, predicate: Instruction.() -> Boolean ): Int { - var instructions = this.implementation!!.instructions + if (implementation == null) { + return -1 + } + var instructions = implementation!!.instructions if (startIndex != null) { instructions = instructions.take(startIndex + 1) } @@ -313,10 +323,10 @@ fun Method.indexOfFirstInstructionReversed( */ fun Method.indexOfFirstInstructionReversedOrThrow( startIndex: Int? = null, - targetOpcode: Opcode + opcode: Opcode ): Int = indexOfFirstInstructionReversedOrThrow(startIndex) { - opcode == targetOpcode + this.opcode == opcode } /** @@ -365,40 +375,59 @@ fun Method.findOpcodeIndicesReversed(filter: Instruction.() -> Boolean): List (instruction as? WideLiteralInstruction)?.wideLiteral == literal } } ?: -1 -fun Method.getStringInstructionIndex(value: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.CONST_STRING - && (instruction as? ReferenceInstruction)?.reference.toString() == value - } -} ?: -1 -fun Method.getStartsWithStringInstructionIndex(value: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.opcode == Opcode.CONST_STRING - && (instruction as? ReferenceInstruction)?.reference.toString().startsWith(value) +/** + * Find the index of the first wide literal instruction with the given value, + * or throw an exception if not found. + * + * @return the first literal instruction with the value, or throws [PatchException] if not found. + */ +fun Method.indexOfFirstWideLiteralInstructionValueOrThrow(literal: Long): Int { + val index = indexOfFirstWideLiteralInstructionValue(literal) + if (index < 0) { + val value = + if (literal >= 2130706432) // 0x7f000000, general resource id + String.format("%#X", literal).lowercase() + else + literal.toString() + + throw PatchException("Found literal value: '$value' but method does not contain the id: $this") } -} ?: -1 + + return index +} + +fun Method.indexOfFirstStringInstruction(str: String) = + indexOfFirstInstruction { + opcode == Opcode.CONST_STRING && + getReference()?.string == str + } + + +fun Method.indexOfFirstStringInstructionOrThrow(str: String): Int { + val index = indexOfFirstStringInstruction(str) + if (index < 0) { + throw PatchException("Found string value for: '$str' but method does not contain the id: $this") + } + + return index +} /** * Check if the method contains a literal with the given value. * * @return if the method contains a literal with the given value. */ -fun Method.containsWideLiteralInstructionIndex(literal: Long) = - getWideLiteralInstructionIndex(literal) >= 0 - -fun Method.containsMethodReferenceNameInstructionIndex(methodName: String) = - getTargetIndexWithMethodReferenceName(methodName) >= 0 - -fun Method.containsReferenceInstructionIndex(reference: String) = - getTargetIndexWithReference(reference) >= 0 +fun Method.containsWideLiteralInstructionValue(literal: Long) = + indexOfFirstWideLiteralInstructionValue(literal) >= 0 /** * Traverse the class hierarchy starting from the given root class. @@ -427,305 +456,12 @@ 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) = - indexOfFirstInstruction(0, predicate) - -/** - * Get the index of the first [Instruction] that matches the predicate, starting from [startIndex]. - * - * @param startIndex Optional starting index to start searching from. - * @return -1 if the instruction is not found. - * @see indexOfFirstInstructionOrThrow - */ -fun Method.indexOfFirstInstruction(startIndex: Int = 0, targetOpcode: Opcode): Int = - indexOfFirstInstruction(startIndex) { - opcode == targetOpcode - } - -fun MutableMethod.getTargetIndexOrThrow(opcode: Opcode) = - getTargetIndexOrThrow(0, opcode) - -fun MutableMethod.getTargetIndexOrThrow(startIndex: Int, opcode: Opcode) = - checkIndex(getTargetIndex(startIndex, opcode), startIndex, opcode) - -fun MutableMethod.getTargetIndexReversedOrThrow(opcode: Opcode) = - getTargetIndexReversedOrThrow(implementation!!.instructions.lastIndex, opcode) - -fun MutableMethod.getTargetIndexReversedOrThrow(startIndex: Int, opcode: Opcode) = - checkIndex(getTargetIndexReversed(startIndex, opcode), startIndex, opcode) - -fun Method.getTargetIndexWithFieldReferenceNameOrThrow(filedName: String) = - checkIndex(getTargetIndexWithFieldReferenceName(filedName), 0, filedName) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameOrThrow(startIndex: Int, filedName: String) = - checkIndex(getTargetIndexWithFieldReferenceName(startIndex, filedName), startIndex, filedName) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversedOrThrow(returnType: String) = - getTargetIndexWithFieldReferenceNameReversedOrThrow( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversedOrThrow( - startIndex: Int, - returnType: String -) = - checkIndex( - getTargetIndexWithFieldReferenceNameReversed(startIndex, returnType), - startIndex, - returnType - ) - -fun Method.getTargetIndexWithFieldReferenceTypeOrThrow(returnType: String) = - checkIndex(getTargetIndexWithFieldReferenceType(returnType), 0, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeOrThrow(startIndex: Int, returnType: String) = - checkIndex(getTargetIndexWithFieldReferenceType(startIndex, returnType), startIndex, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversedOrThrow(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversedOrThrow( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversedOrThrow( - startIndex: Int, - returnType: String -) = - checkIndex( - getTargetIndexWithFieldReferenceTypeReversed(startIndex, returnType), - startIndex, - returnType - ) - -fun Method.getTargetIndexWithMethodReferenceNameOrThrow(methodName: String) = - checkIndex(getTargetIndexWithMethodReferenceName(methodName), 0, methodName) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameOrThrow( - startIndex: Int, - methodName: String -) = - checkIndex( - getTargetIndexWithMethodReferenceName(startIndex, methodName), - startIndex, - methodName - ) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversedOrThrow(methodName: String) = - getTargetIndexWithMethodReferenceNameReversedOrThrow( - implementation!!.instructions.lastIndex, - methodName - ) - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversedOrThrow( - startIndex: Int, - methodName: String -) = - checkIndex( - getTargetIndexWithMethodReferenceNameReversed(startIndex, methodName), - startIndex, - methodName - ) - -fun Method.getTargetIndexWithReferenceOrThrow(reference: String) = - checkIndex(getTargetIndexWithReference(reference), 0, reference) - -fun MutableMethod.getTargetIndexWithReferenceOrThrow(startIndex: Int, reference: String) = - checkIndex(getTargetIndexWithReference(startIndex, reference), startIndex, reference) - -fun MutableMethod.getTargetIndexWithReferenceReversedOrThrow(reference: String) = - getTargetIndexWithReferenceReversedOrThrow(implementation!!.instructions.lastIndex, reference) - -fun MutableMethod.getTargetIndexWithReferenceReversedOrThrow(startIndex: Int, reference: String) = - checkIndex(getTargetIndexWithReferenceReversed(startIndex, reference), startIndex, reference) - -fun checkIndex(index: Int, startIndex: Int, opcode: Opcode): Int { - if (index < 0) { - throw PatchException("Target index not found. startIndex: $startIndex, opcode: $opcode") - } - return index -} - -fun checkIndex(index: Int, startIndex: Int, name: String): Int { - if (index < 0) { - throw PatchException("Target index not found. startIndex: $startIndex, name: $name") - } - return index -} - -fun MutableMethod.getTargetIndex(opcode: Opcode) = getTargetIndex(0, opcode) - -fun MutableMethod.getTargetIndex(startIndex: Int, opcode: Opcode) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.opcode == opcode - } - } - -fun MutableMethod.getTargetIndexReversed(opcode: Opcode) = - getTargetIndexReversed(implementation!!.instructions.size - 1, opcode) - -fun MutableMethod.getTargetIndexReversed(startIndex: Int, opcode: Opcode): Int { - for (index in startIndex downTo 0) { - if (getInstruction(index).opcode != opcode) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithFieldReferenceName(filedName: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.name == filedName - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithFieldReferenceName(startIndex: Int, filedName: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.lastIndex).indexOfFirst { instruction -> - instruction.getReference()?.name == filedName - } - } - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversed( - implementation!!.instructions.lastIndex, - returnType - ) - -fun MutableMethod.getTargetIndexWithFieldReferenceNameReversed( - startIndex: Int, - filedName: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.name != filedName) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithFieldReferenceType(returnType: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.type == returnType - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed(returnType: String) = - getTargetIndexWithFieldReferenceTypeReversed(implementation!!.instructions.size - 1, returnType) - -fun MutableMethod.getTargetIndexWithFieldReferenceType(startIndex: Int, returnType: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.getReference()?.type == returnType - } - } - -fun MutableMethod.getTargetIndexWithFieldReferenceTypeReversed( - startIndex: Int, - returnType: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.type != returnType) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithMethodReferenceName(methodName: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - instruction.getReference()?.name == methodName - } -} ?: -1 - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(methodName: String) = - getTargetIndexWithMethodReferenceNameReversed( - implementation!!.instructions.size - 1, - methodName - ) - - -fun MutableMethod.getTargetIndexWithMethodReferenceName(startIndex: Int, methodName: String) = - implementation!!.instructions.let { - startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> - instruction.getReference()?.name == methodName - } - } - -fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed( - startIndex: Int, - methodName: String -): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (instruction.getReference()?.name != methodName) - continue - - return index - } - return -1 -} - -fun Method.getTargetIndexWithReference(reference: String) = implementation?.let { - it.instructions.indexOfFirst { instruction -> - (instruction as? ReferenceInstruction)?.reference.toString().contains(reference) - } -} ?: -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 -> - (instruction as? ReferenceInstruction)?.reference.toString().contains(reference) - } - } - -fun MutableMethod.getTargetIndexWithReferenceReversed(startIndex: Int, reference: String): Int { - for (index in startIndex downTo 0) { - val instruction = getInstruction(index) - if (!(instruction as? ReferenceInstruction)?.reference.toString().contains(reference)) - continue - - return index - } - return -1 -} - fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, offset: Int) = mutableMethod.getWalkerMethod(context, offset) /** - * MethodWalker structural limitations cause incorrect class to be found - * - * MethodReference to find in YouTube 18.29.38: - * 'Lng;->d(Lou;)Z' - * - * Class found by MethodWalker in YouTube 18.29.38: - * 'Lcom/google/android/gms/maps/model/LatLng;' - * - * The reason this error occurs is because [BytecodeContext.findClass] checks whether className is included or not - * - * In ReVanced Patcher 19.3.1: - * fun findClass(className: String) = findClass { it.type.contains(className) } - * - * (Class 'Lcom/google/android/gms/maps/model/LatLng;' is returned because class 'Lcom/google/android/gms/maps/model/LatLng;' contains keyword 'Lng;') + * MethodWalker can find the wrong class: + * https://github.com/ReVanced/revanced-patcher/issues/309 * * As a workaround, redefine MethodWalker here */ diff --git a/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt index 293855da4..ea7cf3ebb 100644 --- a/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt +++ b/src/main/kotlin/app/revanced/util/fingerprint/LiteralValueFingerprint.kt @@ -1,7 +1,7 @@ package app.revanced.util.fingerprint import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsWideLiteralInstructionIndex +import app.revanced.util.containsWideLiteralInstructionValue import com.android.tools.smali.dexlib2.Opcode /** @@ -29,6 +29,6 @@ abstract class LiteralValueFingerprint( opcodes = opcodes, strings = strings, customFingerprint = { methodDef, _ -> - methodDef.containsWideLiteralInstructionIndex(literalSupplier()) + methodDef.containsWideLiteralInstructionValue(literalSupplier()) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt deleted file mode 100644 index f2252f881..000000000 --- a/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -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 diff --git a/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt deleted file mode 100644 index 69cb6b057..000000000 --- a/src/main/kotlin/app/revanced/util/fingerprint/ReferenceFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.util.fingerprint - -import app.revanced.patcher.fingerprint.MethodFingerprint -import app.revanced.util.containsReferenceInstructionIndex -import com.android.tools.smali.dexlib2.Opcode - -/** - * A fingerprint to resolve methods that contain a specific reference 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 reference value to check for. - */ -abstract class ReferenceFingerprint( - 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.containsReferenceInstructionIndex(reference()) - } -) \ No newline at end of file