From 0752ff0d7216577233ed9ac33b29042f8b461410 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Wed, 25 Sep 2024 21:44:05 +0900 Subject: [PATCH] chore: remove obsolete code --- .../components/FlyoutMenuComponentsPatch.kt | 53 ++--- .../components/PlayerComponentsPatch.kt | 18 +- .../utils/flyoutmenu/FlyoutMenuHookPatch.kt | 11 +- .../utils/resourceid/SharedResourceIdPatch.kt | 2 +- .../sponsorblock/SponsorBlockBytecodePatch.kt | 14 +- .../information/VideoInformationPatch.kt | 26 +-- .../video/playback/VideoPlaybackPatch.kt | 18 +- .../patches/shared/ads/BaseAdsPatch.kt | 3 +- .../integrations/BaseIntegrationsPatch.kt | 8 +- .../patches/shared/litho/LithoFilterPatch.kt | 8 +- .../ViewGroupMarginLayoutParamsHookPatch.kt | 39 ++-- .../general/downloads/DownloadActionsPatch.kt | 32 +-- .../general/music/YouTubeMusicActionsPatch.kt | 35 ++-- .../NavigationBarComponentsPatch.kt | 6 +- .../general/toolbar/ToolBarComponentsPatch.kt | 22 +- .../layout/header/ChangeHeaderPatch.kt | 5 +- .../ambientmode/AmbientModeSwitchPatch.kt | 46 +++-- .../components/PlayerComponentsPatch.kt | 11 +- .../fullscreen/FullscreenComponentsPatch.kt | 32 ++- .../player/seekbar/SeekbarComponentsPatch.kt | 36 ++-- .../player/speedoverlay/SpeedOverlayPatch.kt | 23 +-- .../utils/castbutton/CastButtonPatch.kt | 21 +- .../utils/flyoutmenu/FlyoutMenuHookPatch.kt | 20 +- .../lottie/LottieAnimationViewHookPatch.kt | 28 +-- .../navigation/NavigationBarHookPatch.kt | 7 +- .../playercontrols/PlayerControlsPatch.kt | 22 +- .../utils/playertype/PlayerTypeHookPatch.kt | 88 ++++---- .../ReturnYouTubeDislikeRollingNumberPatch.kt | 195 ++++++++---------- .../shorts/ReturnYouTubeDislikeShortsPatch.kt | 42 ++-- .../information/VideoInformationPatch.kt | 26 +-- .../kotlin/app/revanced/util/BytecodeUtils.kt | 135 ++++++------ 31 files changed, 492 insertions(+), 540 deletions(-) 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 eaae9f555..670cc09dc 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 @@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.flyoutmenu.components.fingerprints.DialogSolidFingerprint import app.revanced.patches.music.flyoutmenu.components.fingerprints.EndButtonsContainerFingerprint @@ -20,11 +19,13 @@ import app.revanced.patches.music.utils.integrations.Constants.COMPONENTS_PATH import app.revanced.patches.music.utils.integrations.Constants.FLYOUT_CLASS_DESCRIPTOR import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.EndButtonsContainer +import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch.TrimSilenceSwitch import app.revanced.patches.music.utils.settings.CategoryType 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.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -95,40 +96,40 @@ object FlyoutMenuComponentsPatch : BaseBytecodePatch( TrimSilenceSwitchFingerprint.resultOrThrow().let { it.mutableMethod.apply { val constIndex = - indexOfFirstWideLiteralInstructionValueOrThrow(SharedResourceIdPatch.TrimSilenceSwitch) + indexOfFirstWideLiteralInstructionValueOrThrow(TrimSilenceSwitch) val onCheckedChangedListenerIndex = indexOfFirstInstructionOrThrow(constIndex, Opcode.INVOKE_DIRECT) val onCheckedChangedListenerReference = getInstruction(onCheckedChangedListenerIndex).reference val onCheckedChangedListenerDefiningClass = (onCheckedChangedListenerReference as MethodReference).definingClass - val onCheckedChangedListenerClass = - context.findClass(onCheckedChangedListenerDefiningClass)!!.mutableClass - onCheckedChangedListenerClass.methods.find { method -> method.name == "onCheckedChanged" } - ?.apply { - val walkerIndex = indexOfFirstInstructionOrThrow { - val reference = - ((this as? ReferenceInstruction)?.reference as? MethodReference) + val onCheckedChangedMethod = + context.findMethodOrThrow(onCheckedChangedListenerDefiningClass) { + name == "onCheckedChanged" + } - opcode == Opcode.INVOKE_VIRTUAL - && reference?.returnType == "V" - && reference.parameterTypes.size == 1 - && reference.parameterTypes[0] == "Z" - } - getWalkerMethod(context, walkerIndex).apply { - val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) - val insertRegister = - getInstruction(insertIndex).registerA + val onCheckedChangedWalkerIndex = + onCheckedChangedMethod.indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_VIRTUAL + && reference?.returnType == "V" + && reference.parameterTypes.size == 1 + && reference.parameterTypes[0] == "Z" + } - addInstructions( - insertIndex + 1, """ - invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z - move-result v$insertRegister - """ - ) - } - } ?: throw PatchException("onClickClass not found!") + getWalkerMethod(context, onCheckedChangedWalkerIndex).apply { + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT) + val insertRegister = + getInstruction(insertIndex).registerA + + addInstructions( + insertIndex + 1, """ + invoke-static {v$insertRegister}, $FLYOUT_CLASS_DESCRIPTOR->enableTrimSilenceSwitch(Z)Z + move-result v$insertRegister + """ + ) + } } } 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 fa76accb5..1cead791f 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 @@ -62,6 +62,7 @@ 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.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -539,7 +540,7 @@ object PlayerComponentsPatch : BaseBytecodePatch( opcode == Opcode.INVOKE_VIRTUAL && reference?.definingClass == "Lcom/google/android/material/bottomsheet/BottomSheetBehavior;" && reference.parameterTypes.first() == "Z" - } + } val freeRegister = getInstruction(bottomSheetBehaviorIndex).registerD @@ -908,7 +909,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( MppWatchWhileLayoutFingerprint.resultOrThrow().mutableMethod.apply { val callableIndex = MppWatchWhileLayoutFingerprint.indexOfCallableInstruction(this) - val insertIndex = indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE) + val insertIndex = + indexOfFirstInstructionReversedOrThrow(callableIndex, Opcode.NEW_INSTANCE) val insertRegister = getInstruction(insertIndex).registerA addInstructionsWithLabels( @@ -929,7 +931,8 @@ object PlayerComponentsPatch : BaseBytecodePatch( ).let { it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.endIndex - val targetRegister = getInstruction(targetIndex).registerA + val targetRegister = + getInstruction(targetIndex).registerA addInstructions( targetIndex + 1, """ @@ -1095,16 +1098,13 @@ object PlayerComponentsPatch : BaseBytecodePatch( val onClickReference = getInstruction(onClickIndex).reference val onClickReferenceDefiningClass = (onClickReference as MethodReference).definingClass - val onClickClass = - context.findClass(onClickReferenceDefiningClass)!!.mutableClass - - onClickClass.methods.find { method -> method.name == "" } - ?.apply { + context.findMethodOrThrow(onClickReferenceDefiningClass) + .apply { addInstruction( implementation!!.instructions.lastIndex, "sput-object p0, $PLAYER_CLASS_DESCRIPTOR->$fieldName:$onClickReferenceDefiningClass" ) - } ?: throw PatchException("onClickClass not found!") + } PlayerPatchConstructorFingerprint.resultOrThrow().let { val mutableClass = it.mutableClass diff --git a/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt index 37c876d38..53ea63ec3 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/flyoutmenu/FlyoutMenuHookPatch.kt @@ -6,7 +6,7 @@ import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.utils.flyoutmenu.fingerprints.PlaybackRateBottomSheetClassFingerprint import app.revanced.patches.music.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.music.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.resultOrThrow @Patch( @@ -31,15 +31,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - context.findClass( - INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR - )!!.mutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showPlaybackSpeedFlyoutMenu", "playbackRateBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt index ebfedb344..c3ad292b2 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt @@ -7,8 +7,8 @@ import app.revanced.patches.shared.mapping.ResourceMappingPatch import app.revanced.patches.shared.mapping.ResourceMappingPatch.getId import app.revanced.patches.shared.mapping.ResourceType.BOOL import app.revanced.patches.shared.mapping.ResourceType.COLOR -import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE import app.revanced.patches.shared.mapping.ResourceType.DIMEN +import app.revanced.patches.shared.mapping.ResourceType.DRAWABLE import app.revanced.patches.shared.mapping.ResourceType.ID import app.revanced.patches.shared.mapping.ResourceType.LAYOUT import app.revanced.patches.shared.mapping.ResourceType.STRING 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 cd6ea4831..6f6cb84b3 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 @@ -61,11 +61,13 @@ object SponsorBlockBytecodePatch : BytecodePatch( RectangleFieldInvalidatorFingerprint.alsoResolve( context, SeekBarConstructorFingerprint ).let { - with (it.mutableMethod) { - val invalidateIndex = RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this) - val rectangleIndex = indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { - getReference()?.type == "Landroid/graphics/Rect;" - } + with(it.mutableMethod) { + val invalidateIndex = + RectangleFieldInvalidatorFingerprint.indexOfInvalidateInstruction(this) + val rectangleIndex = + indexOfFirstInstructionReversedOrThrow(invalidateIndex + 1) { + getReference()?.type == "Landroid/graphics/Rect;" + } val rectangleReference = getInstruction(rectangleIndex).reference @@ -116,7 +118,7 @@ object SponsorBlockBytecodePatch : BytecodePatch( */ rectangleFieldName = MusicPlaybackControlsTimeBarOnMeasureFingerprint.resultOrThrow().let { - with (it.mutableMethod) { + with(it.mutableMethod) { val rectangleIndex = it.scanResult.patternScanResult!!.startIndex val rectangleReference = getInstruction(rectangleIndex).reference 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 be7131c77..8dd9730a7 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 @@ -9,7 +9,6 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions @@ -24,7 +23,7 @@ import app.revanced.patches.music.video.information.fingerprints.VideoQualityLis import app.revanced.patches.music.video.information.fingerprints.VideoQualityTextFingerprint import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.alsoResolve import app.revanced.util.getReference import app.revanced.util.getWalkerMethod @@ -82,7 +81,6 @@ object VideoInformationPatch : BytecodePatch( private var seekSourceEnumType = "" private var seekSourceMethodName = "" - private lateinit var videoInformationMutableClass: MutableClass private lateinit var context: BytecodeContext private lateinit var playerConstructorMethod: MutableMethod @@ -138,21 +136,18 @@ object VideoInformationPatch : BytecodePatch( return v0 """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, methodName, fieldName, definingClass, - smaliInstructions, - true + smaliInstructions ) } } override fun execute(context: BytecodeContext) { this.context = context - videoInformationMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass VideoEndFingerprint.resultOrThrow().let { it.mutableMethod.apply { @@ -211,9 +206,9 @@ object VideoInformationPatch : BytecodePatch( PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR = getInstruction(playerResponseModelIndex) - .getReference() - ?.definingClass - ?: throw PatchException("Could not find Player Response Model class") + .getReference() + ?.definingClass + ?: throw PatchException("Could not find Player Response Model class") videoIdMethodCall = VideoIdFingerprint.getPlayerResponseInstruction("Ljava/lang/String;") @@ -302,13 +297,12 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + VideoInformationPatch.context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overrideVideoQuality", "videoQualityClass", videoQualityClass, - smaliInstructions, - true + smaliInstructions ) } 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 804897727..6c58a8c67 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 @@ -12,12 +12,13 @@ import app.revanced.patches.music.utils.settings.SettingsPatch 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.util.findMethodOrThrow 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.builder.instruction.BuilderInstruction21c 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 @Suppress("unused") @@ -84,19 +85,14 @@ object VideoPlaybackPatch : BaseBytecodePatch( it.mutableMethod.apply { val endIndex = it.scanResult.patternScanResult!!.endIndex val qualityChangedClass = - context.findClass( - (getInstruction(endIndex)) - .reference.toString() - )!! - .mutableClass + getInstruction(endIndex).reference.toString() - val onItemClickMethod = - qualityChangedClass.methods.find { method -> method.name == "onItemClick" } - - onItemClickMethod?.addInstruction( + context.findMethodOrThrow(qualityChangedClass) { + name == "onItemClick" + }.addInstruction( 0, "invoke-static {}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userSelectedVideoQuality()V" - ) ?: throw PatchException("Failed to find onItemClick method") + ) } } 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 1988df271..931751c76 100644 --- a/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/ads/BaseAdsPatch.kt @@ -41,8 +41,7 @@ abstract class BaseAdsPatch( MusicAdsFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = indexOfFirstInstructionOrThrow { - val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) - + val reference = getReference() opcode == Opcode.INVOKE_VIRTUAL && reference?.returnType == "V" && reference.parameterTypes.size == 1 diff --git a/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt index c00eb6273..6d6b9c9ba 100644 --- a/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/integrations/BaseIntegrationsPatch.kt @@ -4,9 +4,9 @@ import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patches.shared.integrations.BaseIntegrationsPatch.IntegrationsFingerprint.IRegisterResolver import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR +import app.revanced.util.findMethodOrThrow import app.revanced.util.isDeprecated import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -18,11 +18,7 @@ abstract class BaseIntegrationsPatch( ) : BytecodePatch(hooks) { override fun execute(context: BytecodeContext) { - if (context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) == null) { - throw PatchException( - "Integrations have not been merged yet. This patch can not succeed without merging the integrations.", - ) - } + context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) hooks.forEach { hook -> hook.invoke(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) 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 5536ceaec..5f3092409 100644 --- a/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt @@ -7,7 +7,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.ExternalLabel @@ -15,6 +14,7 @@ import app.revanced.patches.shared.integrations.Constants.COMPONENTS_PATH 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.findMethodsOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow @@ -156,10 +156,8 @@ object LithoFilterPatch : BytecodePatch( // Create a new method to get the filter array to avoid register conflicts. // This fixes an issue with Integrations compiled with Android Gradle Plugin 8.3.0+. // https://github.com/ReVanced/revanced-patches/issues/2818 - val lithoFilterMethods = context.findClass(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR) - ?.mutableClass - ?.methods - ?: throw PatchException("LithoFilterPatch class not found.") + val lithoFilterMethods = + context.findMethodsOrThrow(INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR) lithoFilterMethods .first { it.name == "" } diff --git a/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt b/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt index 3dfe48d4c..b504a8a7f 100644 --- a/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/shared/viewgroup/ViewGroupMarginLayoutParamsHookPatch.kt @@ -3,12 +3,12 @@ package app.revanced.patches.shared.viewgroup import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginFingerprint import app.revanced.patches.shared.viewgroup.fingerprints.ViewGroupMarginParentFingerprint -import app.revanced.util.resultOrThrow +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow @Patch( description = "Hook YouTube or YouTube Music to use ViewGroup.MarginLayoutParams in the integration.", @@ -18,26 +18,21 @@ object ViewGroupMarginLayoutParamsHookPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext) { - val method = - context.findClass(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> - method.name == "hideViewGroupByMarginLayoutParams" - } ?: throw PatchException("Could not find hideViewGroupByMarginLayoutParams method") - - ViewGroupMarginFingerprint.resolve( - context, - ViewGroupMarginParentFingerprint.resultOrThrow().classDef - ) - ViewGroupMarginFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val setViewGroupMarginCall = "$definingClass->$name(Landroid/view/View;II)V" - - method.addInstructions( - 0, """ - const/4 v0, 0x0 - invoke-static {p0, v0, v0}, $setViewGroupMarginCall - """ - ) - } + val setViewGroupMarginCall = with( + ViewGroupMarginFingerprint.alsoResolve( + context, ViewGroupMarginParentFingerprint + ).mutableMethod + ) { + "$definingClass->$name(Landroid/view/View;II)V" } + + context.findMethodOrThrow(INTEGRATIONS_UTILS_CLASS_DESCRIPTOR) { + name == "hideViewGroupByMarginLayoutParams" + }.addInstructions( + 0, """ + const/4 v0, 0x0 + invoke-static {p0, v0, v0}, $setViewGroupMarginCall + """ + ) } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt index 9f426080b..688d34454 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/downloads/DownloadActionsPatch.kt @@ -19,6 +19,7 @@ import app.revanced.patches.youtube.utils.pip.PiPStateHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch @@ -87,23 +88,22 @@ object DownloadActionsPatch : BaseBytecodePatch( ?: throw PatchException("Could not find onClickListenerClass") } - context.findClass(onClickListenerClass) - ?.mutableClass - ?.methods - ?.first { method -> method.name == "onClick" }?.apply { - val insertIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_STATIC - && getReference()?.name == "isEmpty" - } - val insertRegister = getInstruction(insertIndex).registerC + context.findMethodOrThrow(onClickListenerClass) { + name == "onClick" + }.apply { + val insertIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_STATIC + && getReference()?.name == "isEmpty" + } + val insertRegister = getInstruction(insertIndex).registerC - addInstructions( - insertIndex, """ - invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$insertRegister - """ - ) - } ?: throw PatchException("Could not find class $onClickListenerClass") + addInstructions( + insertIndex, """ + invoke-static {v$insertRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->inAppPlaylistDownloadButtonOnClick(Ljava/lang/String;)Ljava/lang/String; + move-result-object v$insertRegister + """ + ) + } OfflinePlaylistEndpointFingerprint.resultOrThrow().mutableMethod.apply { val playlistIdParameter = parameterTypes.indexOf("Ljava/lang/String;") + 1 diff --git a/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt index acf3b1d00..9b49e8603 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/general/music/YouTubeMusicActionsPatch.kt @@ -11,6 +11,7 @@ import app.revanced.patches.youtube.utils.integrations.Constants.GENERAL_PATH import app.revanced.patches.youtube.utils.settings.ResourceUtils.addEntryValues import app.revanced.patches.youtube.utils.settings.SettingsBytecodePatch import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.patch.BaseBytecodePatch @@ -39,13 +40,15 @@ object YouTubeMusicActionsPatch : BaseBytecodePatch( AppDeepLinkFingerprint.resultOrThrow().let { it.mutableMethod.apply { val packageNameIndex = it.scanResult.patternScanResult!!.startIndex - val packageNameField = getInstruction(packageNameIndex).reference.toString() + val packageNameField = + getInstruction(packageNameIndex).reference.toString() implementation!!.instructions .withIndex() .filter { (_, instruction) -> instruction.opcode == Opcode.IGET_OBJECT && - instruction.getReference()?.toString() == packageNameField + instruction.getReference() + ?.toString() == packageNameField } .map { (index, _) -> index } .reversed() @@ -78,30 +81,28 @@ object YouTubeMusicActionsPatch : BaseBytecodePatch( override fun close() { if (SettingsPatch.containsPatch("GmsCore support")) { + val musicPackageName = PackageNameYouTubeMusic.valueOrThrow() SettingsPatch.contexts.addEntryValues( "revanced_third_party_youtube_music_label", "RVX Music" ) SettingsPatch.contexts.addEntryValues( "revanced_third_party_youtube_music_package_name", - PackageNameYouTubeMusic.valueOrThrow() + musicPackageName ) - SettingsBytecodePatch.contexts - .findClass { classDef -> classDef.type == INTEGRATIONS_CLASS_DESCRIPTOR } - ?.mutableClass - ?.methods - ?.first { method -> method.name == "getRVXMusicPackageName" } - ?.apply { - val replaceIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) - val replaceRegister = - getInstruction(replaceIndex).registerA + SettingsBytecodePatch.contexts.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "getRVXMusicPackageName" + }.apply { + val replaceIndex = indexOfFirstInstructionOrThrow(Opcode.CONST_STRING) + val replaceRegister = + getInstruction(replaceIndex).registerA - replaceInstruction( - replaceIndex, - "const-string v$replaceRegister, \"${PackageNameYouTubeMusic.valueOrThrow()}\"" - ) - } + replaceInstruction( + replaceIndex, + "const-string v$replaceRegister, \"$musicPackageName\"" + ) + } } } 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 20376d1a5..6d2e52943 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 @@ -89,12 +89,12 @@ object NavigationBarComponentsPatch : BaseBytecodePatch( AutoMotiveFingerprint.resultOrThrow().let { it.mutableMethod.apply { val insertIndex = indexOfFirstStringInstructionOrThrow("Android Automotive") - 1 - val register = getInstruction(insertIndex).registerA + val insertRegister = getInstruction(insertIndex).registerA addInstructions( insertIndex, """ - invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z - move-result v$register + invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->switchCreateWithNotificationButton(Z)Z + move-result v$insertRegister """ ) } 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 e68cf7155..911ecb988 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 @@ -41,6 +41,7 @@ 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.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -114,8 +115,8 @@ object ToolBarComponentsPatch : BaseBytecodePatch( val attributeResolverMethodCall = attributeResolverMethod.definingClass + "->" + attributeResolverMethod.name + "(Landroid/content/Context;I)Landroid/graphics/drawable/Drawable;" - context.findClass(GENERAL_CLASS_DESCRIPTOR)!!.mutableClass.methods.single { method -> - method.name == "getHeaderDrawable" + context.findMethodOrThrow(GENERAL_CLASS_DESCRIPTOR) { + name == "getHeaderDrawable" }.addInstructions( 0, """ invoke-static {p0, p1}, $attributeResolverMethodCall @@ -381,15 +382,14 @@ object ToolBarComponentsPatch : BaseBytecodePatch( ToolBarHookPatch.hook("$GENERAL_CLASS_DESCRIPTOR->replaceCreateButton") - val settingsClass = context.findClass("Shell_SettingsActivity") - ?: throw PatchException("Shell_SettingsActivity class not found.") - - settingsClass.mutableClass.methods.find { it.name == "onCreate" }?.apply { - addInstruction( - 0, - "invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V" - ) - } ?: throw PatchException("onCreate method not found.") + context.findMethodOrThrow( + "Lcom/google/android/apps/youtube/app/application/Shell_SettingsActivity;" + ) { + name == "onCreate" + }.addInstruction( + 0, + "invoke-static {p0}, $GENERAL_CLASS_DESCRIPTOR->setShellActivityTheme(Landroid/app/Activity;)V" + ) // endregion diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt index f733be559..57b2c90dc 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/header/ChangeHeaderPatch.kt @@ -141,7 +141,10 @@ object ChangeHeaderPatch : BaseResourcePatch( } if (customBrandingIconType == "youtube_minimal_header") { - SettingsBytecodePatch.contexts.updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "MinimalHeader") + SettingsBytecodePatch.contexts.updatePatchStatus( + PATCH_STATUS_CLASS_DESCRIPTOR, + "MinimalHeader" + ) } } else { println(warnings) 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 0e4475e9b..f5179bfe7 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 @@ -3,13 +3,13 @@ package app.revanced.patches.youtube.player.ambientmode import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.PatchException import app.revanced.patches.youtube.player.ambientmode.fingerprints.AmbientModeInFullscreenFingerprint import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeBroadcastReceiverFingerprint import app.revanced.patches.youtube.player.ambientmode.fingerprints.PowerSaveModeSyntheticFingerprint 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.findMethodOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstStringInstructionOrThrow @@ -19,7 +19,6 @@ 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.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Suppress("unused") @@ -60,27 +59,30 @@ object AmbientModeSwitchPatch : BaseBytecodePatch( } syntheticClassList.distinct().forEach { className -> - context.findClass(className)?.mutableClass?.methods?.first { method -> - method.name == "accept" - }?.apply { - for (index in implementation!!.instructions.size - 1 downTo 0) { - val instruction = getInstruction(index) - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) - continue + context.findMethodOrThrow(className) { + name == "accept" + }.apply { + implementation!!.instructions + .withIndex() + .filter { (_, instruction) -> + val reference = (instruction as? ReferenceInstruction)?.reference + instruction.opcode == Opcode.INVOKE_VIRTUAL && + reference is MethodReference && + reference.name == "isPowerSaveMode" + } + .map { (index, _) -> index } + .reversed() + .forEach { index -> + val register = getInstruction(index + 1).registerA - if (((instruction as Instruction35c).reference as MethodReference).name != "isPowerSaveMode") - continue - - val register = getInstruction(index + 1).registerA - - addInstructions( - index + 2, """ - invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z - move-result v$register - """ - ) - } - } ?: throw PatchException("Could not find $className") + addInstructions( + index + 2, """ + invoke-static {v$register}, $PLAYER_CLASS_DESCRIPTOR->bypassAmbientModeRestrictions(Z)Z + move-result v$register + """ + ) + } + } } // endregion 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 6deb71687..94fabf899 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,6 +48,7 @@ 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.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow @@ -146,15 +147,13 @@ object PlayerComponentsPatch : BaseBytecodePatch( hookInitVideoPanel(1) } else { val syntheticIndex = - indexOfFirstInstructionOrThrow(opcode = Opcode.NEW_INSTANCE) + indexOfFirstInstructionOrThrow(Opcode.NEW_INSTANCE) val syntheticReference = getInstruction(syntheticIndex).reference.toString() - val syntheticClass = - context.findClass(syntheticReference)!!.mutableClass - syntheticClass.methods.find { method -> method.name == "onClick" } - ?.hookInitVideoPanel(0) - ?: throw PatchException("Could not find onClick method in $syntheticReference") + context.findMethodOrThrow(syntheticReference) { + name == "onClick" + }.hookInitVideoPanel(0) } } } 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 852fab2a1..4846391cc 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 @@ -29,6 +29,7 @@ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.AutoN import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.FullScreenEngagementPanel import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.QuickActionsElementContainer import app.revanced.patches.youtube.utils.settings.SettingsPatch +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -253,18 +254,16 @@ object FullscreenComponentsPatch : BaseBytecodePatch( val invokeIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.INVOKE_INTERFACE) val targetIndex = indexOfFirstInstructionOrThrow(invokeIndex, Opcode.CHECK_CAST) - val targetClass = context - .findClass(getInstruction(targetIndex).reference.toString())!! - .mutableClass + val targetClass = + getInstruction(targetIndex).reference.toString() // add an instruction to check the vertical video - targetClass.methods.find { method -> method.parameters == listOf("I", "I", "Z") } - ?.apply { - addInstruction( - 1, - "invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V" - ) - } ?: throw PatchException("Could not find targetMethod") + context.findMethodOrThrow(targetClass) { + parameters == listOf("I", "I", "Z") + }.addInstruction( + 1, + "invoke-static {p1, p2}, $PLAYER_CLASS_DESCRIPTOR->setVideoPortrait(II)V" + ) } } @@ -281,14 +280,11 @@ object FullscreenComponentsPatch : BaseBytecodePatch( } val walkerMethod = getWalkerMethod(context, walkerIndex) - val targetClass = - context.findClass(walkerMethod.definingClass)!!.mutableClass - val constructorMethod = targetClass - .methods - .find { method -> - method.name == "" - && method.parameterTypes == listOf("Landroid/app/Activity;") - } ?: throw PatchException("Constructor method not found!") + val constructorMethod = + context.findMethodOrThrow(walkerMethod.definingClass) { + name == "" && + parameterTypes == listOf("Landroid/app/Activity;") + } arrayOf( walkerMethod, 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 3c454136e..6d93672b7 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,6 +30,7 @@ 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.findMethodsOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow @@ -38,8 +39,6 @@ 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.builder.instruction.BuilderInstruction35c -import com.android.tools.smali.dexlib2.dexbacked.reference.DexBackedMethodReference 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 @@ -84,14 +83,15 @@ object SeekbarComponentsPatch : BaseBytecodePatch( SeekbarTappingFingerprint.resultOrThrow().let { it.mutableMethod.apply { val tapSeekIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val tapSeekReference = getInstruction(tapSeekIndex).reference - val tapSeekClass = - context - .findClass((tapSeekReference as DexBackedMethodReference).definingClass)!! - .mutableClass - val tapSeekMethods = mutableMapOf() + val tapSeekClass = getInstruction(tapSeekIndex) + .getReference()!! + .definingClass - for (method in tapSeekClass.methods) { + val tapSeekMethods = context.findMethodsOrThrow(tapSeekClass) + var pMethodCall = "" + var oMethodCall = "" + + for (method in tapSeekMethods) { if (method.implementation == null) continue @@ -110,15 +110,17 @@ object SeekbarComponentsPatch : BaseBytecodePatch( // method founds if (literal == 1) - tapSeekMethods["P"] = method + pMethodCall = "${method.definingClass}->${method.name}(I)V" else if (literal == 2) - tapSeekMethods["O"] = method + oMethodCall = "${method.definingClass}->${method.name}(I)V" } - val pMethod = tapSeekMethods["P"] - ?: throw PatchException("pMethod not found") - val oMethod = tapSeekMethods["O"] - ?: throw PatchException("oMethod not found") + if (pMethodCall.isEmpty()) { + throw PatchException("pMethod not found") + } + if (oMethodCall.isEmpty()) { + throw PatchException("oMethod not found") + } val insertIndex = it.scanResult.patternScanResult!!.startIndex + 2 @@ -127,8 +129,8 @@ object SeekbarComponentsPatch : BaseBytecodePatch( invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->enableSeekbarTapping()Z move-result v0 if-eqz v0, :disabled - invoke-virtual { p0, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V - invoke-virtual { p0, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V + invoke-virtual { p0, v2 }, $pMethodCall + invoke-virtual { p0, v2 }, $oMethodCall """, ExternalLabel("disabled", getInstruction(insertIndex)) ) } 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 d4de67d25..ae20d453e 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 @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel @@ -20,7 +19,9 @@ import app.revanced.patches.youtube.player.speedoverlay.fingerprints.SpeedOverla 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.findMethodOrThrow import app.revanced.util.getReference +import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.injectLiteralInstructionBooleanCall @@ -33,7 +34,6 @@ 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( @@ -135,16 +135,11 @@ object SpeedOverlayPatch : BytecodePatch( hook(insertIndex, insertRegister, jumpIndex) - val slideToSeekBooleanMethod = context.toMethodWalker(it.mutableMethod) - .nextMethod(scanResult.startIndex + 1, true) - .getMethod() as MutableMethod + val slideToSeekBooleanMethod = + getWalkerMethod(context, scanResult.startIndex + 1) val slideToSeekConstructorMethod = - context.findClass { classDef -> classDef.type == slideToSeekBooleanMethod.definingClass } - ?.mutableClass - ?.methods - ?.find { method -> MethodUtil.isConstructor(method) } - ?: throw PatchException("Could not find constructor method") + context.findMethodOrThrow(slideToSeekBooleanMethod.definingClass) val slideToSeekSyntheticIndex = slideToSeekConstructorMethod .indexOfFirstInstructionReversedOrThrow { @@ -157,11 +152,9 @@ object SpeedOverlayPatch : BytecodePatch( .toString() val slideToSeekSyntheticMethod = - context.findClass { classDef -> classDef.type == slideToSeekSyntheticClass } - ?.mutableClass - ?.methods - ?.find { method -> method.name == "run" } - ?: throw PatchException("Could not find synthetic method") + context.findMethodOrThrow(slideToSeekSyntheticClass) { + name == "run" + } Pair(slideToSeekBooleanMethod, slideToSeekSyntheticMethod) } 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 39ac28f63..01193f893 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 @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.castbutton.fingerprints.MenuItemInitializeFingerprint @@ -18,6 +17,7 @@ import app.revanced.patches.youtube.utils.integrations.Constants.PLAYER_CLASS_DE import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow @@ -50,17 +50,14 @@ object CastButtonPatch : BytecodePatch( playerButtonMethod = PlayerButtonFingerprint.resultOrThrow().mutableMethod - val buttonClass = context.findClass("MediaRouteButton") - ?: throw PatchException("MediaRouteButton class not found.") - - buttonClass.mutableClass.methods.find { it.name == "setVisibility" }?.apply { - addInstructions( - 0, """ - invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I - move-result p1 - """ - ) - } ?: throw PatchException("setVisibility method not found.") + context.findMethodOrThrow("Landroidx/mediarouter/app/MediaRouteButton;") { + name == "setVisibility" + }.addInstructions( + 0, """ + invoke-static {p1}, $INTEGRATIONS_CLASS_DESCRIPTOR->hideCastButton(I)I + move-result p1 + """ + ) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt index 56270f123..f6275602a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/flyoutmenu/FlyoutMenuHookPatch.kt @@ -7,7 +7,7 @@ import app.revanced.patches.youtube.utils.fingerprints.PlaybackRateBottomSheetBu import app.revanced.patches.youtube.utils.flyoutmenu.fingerprints.VideoQualityBottomSheetClassFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.resultOrThrow @Patch( @@ -25,10 +25,6 @@ object FlyoutMenuHookPatch : BytecodePatch( override fun execute(context: BytecodeContext) { - val videoUtilsMutableClass = context.findClass( - INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR - )!!.mutableClass - PlaybackRateBottomSheetBuilderFingerprint.resultOrThrow().let { it.mutableMethod.apply { val smaliInstructions = @@ -39,13 +35,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - videoUtilsMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showPlaybackSpeedFlyoutMenu", "playbackRateBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } @@ -61,13 +56,12 @@ object FlyoutMenuHookPatch : BytecodePatch( return-void """ - videoUtilsMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_VIDEO_UTILS_CLASS_DESCRIPTOR, "showVideoQualityFlyoutMenu", "videoQualityBottomSheetClass", definingClass, - smaliInstructions, - true + smaliInstructions ) } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt index 24e436f45..1d3e106f4 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/lottie/LottieAnimationViewHookPatch.kt @@ -3,11 +3,11 @@ package app.revanced.patches.youtube.utils.lottie import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint import app.revanced.patches.youtube.utils.lottie.fingerprints.SetAnimationFingerprint.LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR +import app.revanced.util.findMethodOrThrow import app.revanced.util.resultOrThrow @Patch( @@ -20,21 +20,15 @@ object LottieAnimationViewHookPatch : BytecodePatch( "$UTILS_PATH/LottieAnimationViewPatch;" override fun execute(context: BytecodeContext) { - - val setAnimationMethodName = SetAnimationFingerprint.resultOrThrow().mutableMethod.name - val setAnimationCall = "invoke-virtual {p0, p1}, " + - LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR + - "->" + - setAnimationMethodName + - "(I)V" - - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR) - ?.mutableClass - ?.methods - ?.first { method -> method.name == "setAnimation" } - ?.addInstruction( - 0, - setAnimationCall - ) ?: throw PatchException("Could not find setAnimation method") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "setAnimation" + }.addInstruction( + 0, + "invoke-virtual {p0, p1}, " + + LOTTIE_ANIMATION_VIEW_CLASS_DESCRIPTOR + + "->" + + SetAnimationFingerprint.resultOrThrow().mutableMethod.name + + "(I)V" + ) } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt index 5ea1cb576..d1082cbfe 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/navigation/NavigationBarHookPatch.kt @@ -18,6 +18,7 @@ import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarButton import app.revanced.patches.youtube.utils.navigation.fingerprints.PivotBarConstructorFingerprint import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -115,9 +116,9 @@ object NavigationBarHookPatch : BytecodePatch( } navigationTabCreatedCallback = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)?.mutableClass?.methods?.first { method -> - method.name == "navigationTabCreatedCallback" - } ?: throw PatchException("Could not find navigationTabCreatedCallback method") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "navigationTabCreatedCallback" + } MainActivityResolvePatch.injectOnBackPressedMethodCall( INTEGRATIONS_CLASS_DESCRIPTOR, 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 638c0fa83..03f5c5ca2 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 @@ -17,6 +17,7 @@ import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerCont import app.revanced.patches.youtube.utils.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.Opcode @@ -115,28 +116,25 @@ object PlayerControlsPatch : BytecodePatch( // region set methods to inject into integration - val playerControlsMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass - changeVisibilityMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "changeVisibility" - && method.parameters == listOf("Z", "Z") + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "changeVisibility" + && parameters == listOf("Z", "Z") } changeVisibilityNegatedImmediatelyMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "changeVisibilityNegatedImmediately" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "changeVisibilityNegatedImmediately" } initializeBottomControlButtonMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "initializeBottomControlButton" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "initializeBottomControlButton" } initializeTopControlButtonMethod = - playerControlsMutableClass.methods.single { method -> - method.name == "initializeTopControlButton" + context.findMethodOrThrow(INTEGRATIONS_CLASS_DESCRIPTOR) { + name == "initializeTopControlButton" } // endregion 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 4dc3d749a..56975e770 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 @@ -15,7 +15,10 @@ import app.revanced.patches.youtube.utils.playertype.fingerprint.BrowseIdClassFi import app.revanced.patches.youtube.utils.playertype.fingerprint.PlayerTypeFingerprint 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.addStaticFieldToIntegration +import app.revanced.util.alsoResolve +import app.revanced.util.findMethodOrThrow +import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.resultOrThrow @@ -57,22 +60,20 @@ object PlayerTypeHookPatch : BytecodePatch( // region patch for set video state - YouTubeControlsOverlayFingerprint.resultOrThrow().let { parentResult -> - VideoStateFingerprint.also { - it.resolve(context, parentResult.classDef) - }.resultOrThrow().let { - it.mutableMethod.apply { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val videoStateFieldName = - getInstruction(endIndex).reference + VideoStateFingerprint.alsoResolve( + context, YouTubeControlsOverlayFingerprint + ).let { + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val videoStateFieldName = + getInstruction(endIndex).reference - addInstructions( - 0, """ - iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field - invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V - """ - ) - } + addInstructions( + 0, """ + iget-object v0, p1, $videoStateFieldName # copy VideoState parameter field + invoke-static {v0}, $INTEGRATIONS_PLAYER_TYPE_HOOK_CLASS_DESCRIPTOR->setVideoState(Ljava/lang/Enum;)V + """ + ) } } @@ -83,39 +84,36 @@ object PlayerTypeHookPatch : BytecodePatch( BrowseIdClassFingerprint.resultOrThrow().let { it.mutableMethod.apply { val targetIndex = indexOfFirstStringInstructionOrThrow("VL") - 1 - val targetReference = getInstruction(targetIndex).reference - val targetClass = - context.findClass((targetReference as FieldReference).definingClass)!!.mutableClass + val targetClass = getInstruction(targetIndex) + .getReference() + ?.definingClass + ?: throw PatchException("Could not find browseId class") - targetClass.methods.find { method -> method.name == "" } - ?.apply { - val browseIdFieldIndex = indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) - val browseIdFieldName = - (getInstruction(browseIdFieldIndex).reference as FieldReference).name + context.findMethodOrThrow(targetClass).apply { + val browseIdFieldReference = getInstruction( + indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) + ).reference + val browseIdFieldName = (browseIdFieldReference as FieldReference).name - val smaliInstructions = + val smaliInstructions = + """ + if-eqz v0, :ignore + iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String; + if-eqz v0, :ignore + return-object v0 + :ignore + const-string v0, "" + return-object v0 """ - if-eqz v0, :ignore - iget-object v0, v0, $definingClass->$browseIdFieldName:Ljava/lang/String; - if-eqz v0, :ignore - return-object v0 - :ignore - const-string v0, "" - return-object v0 - """ - val rootViewMutableClass = - context.findClass(INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR)!!.mutableClass - - rootViewMutableClass.addFieldAndInstructions( - context, - "getBrowseId", - "browseIdClass", - definingClass, - smaliInstructions, - true - ) - } ?: throw PatchException("BrowseIdClass not found!") + context.addStaticFieldToIntegration( + INTEGRATIONS_ROOT_VIEW_HOOK_CLASS_DESCRIPTOR, + "getBrowseId", + "browseIdClass", + definingClass, + smaliInstructions + ) + } } } 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 03931cb73..22256003b 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 @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint @@ -17,6 +16,8 @@ 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.alsoResolve +import app.revanced.util.findMethodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow @@ -26,7 +27,6 @@ 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]) object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( @@ -47,130 +47,115 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch( * 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) { + if (!SettingsPatch.upward1849) { + return + } - RollingNumberSetterFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex - val rollingNumberClassReference = - getInstruction(rollingNumberClassIndex).reference - val rollingNumberClass = - context.findClass(rollingNumberClassReference.toString())!!.mutableClass + RollingNumberSetterFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val rollingNumberClassIndex = it.scanResult.patternScanResult!!.startIndex + val rollingNumberClassReference = + getInstruction(rollingNumberClassIndex).reference.toString() + val rollingNumberConstructorMethod = + context.findMethodOrThrow(rollingNumberClassReference) + val charSequenceFieldReference = with(rollingNumberConstructorMethod) { + getInstruction( + indexOfFirstInstructionOrThrow(Opcode.IPUT_OBJECT) + ).reference + } - lateinit var charSequenceFieldReference: Reference + val insertIndex = rollingNumberClassIndex + 1 + val charSequenceInstanceRegister = + getInstruction(rollingNumberClassIndex).registerA + val registerCount = implementation!!.registerCount - rollingNumberClass.methods.find { method -> method.name == "" } - ?.apply { - val rollingNumberFieldIndex = - indexOfFirstInstructionOrThrow(opcode = Opcode.IPUT_OBJECT) - charSequenceFieldReference = - getInstruction(rollingNumberFieldIndex).reference - } ?: throw PatchException("RollingNumberClass not found!") + // This register is being overwritten, so it is free to use. + val freeRegister = registerCount - 1 + val conversionContextRegister = registerCount - parameters.size + 1 - val insertIndex = rollingNumberClassIndex + 1 - - val charSequenceInstanceRegister = - getInstruction(rollingNumberClassIndex).registerA - - val registerCount = implementation!!.registerCount - - // This register is being overwritten, so it is free to use. - val freeRegister = registerCount - 1 - val conversionContextRegister = registerCount - parameters.size + 1 - - addInstructions( - insertIndex, """ + addInstructions( + insertIndex, """ iget-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference invoke-static {v$conversionContextRegister, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberLoaded(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String; move-result-object v$freeRegister iput-object v$freeRegister, v$charSequenceInstanceRegister, $charSequenceFieldReference """ - ) - } + ) } + } - // Rolling Number text views use the measured width of the raw string for layout. - // Modify the measure text calculation to include the left drawable separator if needed. - RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val measuredTextWidthIndex = endIndex - 2 - val measuredTextWidthRegister = - getInstruction(measuredTextWidthIndex).registerA + // Rolling Number text views use the measured width of the raw string for layout. + // Modify the measure text calculation to include the left drawable separator if needed. + RollingNumberMeasureAnimatedTextFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val measuredTextWidthIndex = endIndex - 2 + val measuredTextWidthRegister = + getInstruction(measuredTextWidthIndex).registerA - addInstructions( - endIndex + 1, """ - invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - move-result v$measuredTextWidthRegister - """ - ) + addInstructions( + endIndex + 1, """ + invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F + move-result v$measuredTextWidthRegister + """ + ) - val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE) - val ifGeInstruction = getInstruction(ifGeIndex) + val ifGeIndex = indexOfFirstInstructionOrThrow(opcode = Opcode.IF_GE) + val ifGeInstruction = getInstruction(ifGeIndex) - removeInstruction(ifGeIndex) - addInstructionsWithLabels( - ifGeIndex, """ - if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump - """, ExternalLabel("jump", getInstruction(endIndex)) - ) - } + removeInstruction(ifGeIndex) + addInstructionsWithLabels( + ifGeIndex, """ + if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump + """, ExternalLabel("jump", getInstruction(endIndex)) + ) } + } - RollingNumberMeasureTextParentFingerprint.resultOrThrow().classDef.let { parentClassDef -> - RollingNumberMeasureStaticLabelFingerprint.resolve(context, parentClassDef) + RollingNumberMeasureStaticLabelFingerprint.alsoResolve( + context, + RollingNumberMeasureTextParentFingerprint + ).let { + it.mutableMethod.apply { + val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1 + val freeRegister = getInstruction(0).registerA - // Additional text measurement method. Used if YouTube decides not to animate the likes count - // and sometimes used for initial video load. - RollingNumberMeasureStaticLabelFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val freeRegister = getInstruction(0).registerA - - addInstructions( - measureTextIndex + 1, """ - move-result v$freeRegister - invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F - """ - ) - } - } + addInstructions( + measureTextIndex + 1, """ + move-result v$freeRegister + invoke-static {p1, v$freeRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F + """ + ) } + } - // The rolling number Span is missing styling since it's initially set as a String. - // Modify the UI text view and use the styled like/dislike Span. - RollingNumberTextViewFingerprint.resultOrThrow().let { parentResult -> - // Initial TextView is set in this method. - val initiallyCreatedTextViewMethod = parentResult.mutableMethod + // The rolling number Span is missing styling since it's initially set as a String. + // Modify the UI text view and use the styled like/dislike Span. + arrayOf( + // Initial TextView is set in this method. + RollingNumberTextViewFingerprint + .resultOrThrow(), - // Video less than 24 hours after uploaded, like counts will be updated in real time. - // Whenever like counts are updated, TextView is set in this method. - val realTimeUpdateTextViewMethod = - RollingNumberTextViewAnimationUpdateFingerprint.also { - it.resolve(context, parentResult.classDef) - }.resultOrThrow().mutableMethod - - arrayOf( - initiallyCreatedTextViewMethod, - realTimeUpdateTextViewMethod - ).forEach { insertMethod -> - insertMethod.apply { - val setTextIndex = indexOfFirstInstructionOrThrow { - getReference()?.name == "setText" - } - val textViewRegister = - getInstruction(setTextIndex).registerC - val textSpanRegister = - getInstruction(setTextIndex).registerD - - addInstructions( - setTextIndex, """ - invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; - move-result-object v$textSpanRegister - """ - ) - } + // Video less than 24 hours after uploaded, like counts will be updated in real time. + // Whenever like counts are updated, TextView is set in this method. + RollingNumberTextViewAnimationUpdateFingerprint + .alsoResolve(context, RollingNumberTextViewFingerprint) + ).forEach { fingerprintResult -> + fingerprintResult.mutableMethod.apply { + val setTextIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "setText" } + val textViewRegister = + getInstruction(setTextIndex).registerC + val textSpanRegister = + getInstruction(setTextIndex).registerD + + addInstructions( + setTextIndex, """ + invoke-static {v$textViewRegister, v$textSpanRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->updateRollingNumber(Landroid/widget/TextView;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + move-result-object v$textSpanRegister + """ + ) } } } 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 25fd45485..d174f5ece 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 @@ -71,28 +71,30 @@ object ReturnYouTubeDislikeShortsPatch : BytecodePatch( } } - if (SettingsPatch.upward1834) { - TextComponentSpecFingerprint.resultOrThrow().let { - it.mutableMethod.apply { - 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 + if (!SettingsPatch.upward1834) { + return + } - addInstructions( - insertIndex + 1, """ - invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; - move-result-object v$charSequenceRegister - invoke-static {v$charSequenceRegister}, $replaceReference - """ - ) - removeInstruction(insertIndex) + TextComponentSpecFingerprint.resultOrThrow().let { + it.mutableMethod.apply { + 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 + + addInstructions( + insertIndex + 1, """ + invoke-static {v$conversionContextRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onCharSequenceLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; + move-result-object v$charSequenceRegister + invoke-static {v$charSequenceRegister}, $replaceReference + """ + ) + removeInstruction(insertIndex) } } } 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 7c532cf12..bda19a0c3 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 @@ -10,11 +10,11 @@ import app.revanced.patcher.fingerprint.MethodFingerprintResult import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.shared.fingerprints.MdxPlayerDirectorSetVideoStageFingerprint +import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.PlayerResponseModelUtils.indexOfPlayerResponseModelInstruction import app.revanced.patches.youtube.utils.fingerprints.VideoEndFingerprint @@ -31,13 +31,12 @@ import app.revanced.patches.youtube.video.information.fingerprints.SeekRelativeF import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintBackgroundPlay import app.revanced.patches.youtube.video.information.fingerprints.VideoIdFingerprintShorts -import app.revanced.patches.shared.fingerprints.VideoLengthFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityListFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoQualityTextFingerprint import app.revanced.patches.youtube.video.information.fingerprints.VideoTitleFingerprint import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch import app.revanced.patches.youtube.video.videoid.VideoIdPatch -import app.revanced.util.addFieldAndInstructions +import app.revanced.util.addStaticFieldToIntegration import app.revanced.util.alsoResolve import app.revanced.util.getReference import app.revanced.util.getWalkerMethod @@ -121,7 +120,6 @@ object VideoInformationPatch : BytecodePatch( private var seekSourceMethodName = "" private var seekRelativeSourceMethodName = "" - private lateinit var videoInformationMutableClass: MutableClass private lateinit var context: BytecodeContext private lateinit var playerConstructorMethod: MutableMethod @@ -179,21 +177,18 @@ object VideoInformationPatch : BytecodePatch( return v0 """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, methodName, fieldName, definingClass, - smaliInstructions, - true + smaliInstructions ) } } override fun execute(context: BytecodeContext) { this.context = context - videoInformationMutableClass = - context.findClass(INTEGRATIONS_CLASS_DESCRIPTOR)!!.mutableClass VideoEndFingerprint.resultOrThrow().let { it.mutableMethod.apply { @@ -449,8 +444,8 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overridePlaybackSpeed", "playbackSpeedClass", playbackSpeedClass, @@ -490,13 +485,12 @@ object VideoInformationPatch : BytecodePatch( return-void """ - videoInformationMutableClass.addFieldAndInstructions( - context, + context.addStaticFieldToIntegration( + INTEGRATIONS_CLASS_DESCRIPTOR, "overrideVideoQuality", "videoQualityClass", videoQualityClass, - smaliInstructions, - true + smaliInstructions ) } diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 686c14fa9..183e3a29c 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -470,87 +470,102 @@ fun MethodFingerprintResult.getWalkerMethod(context: BytecodeContext, offset: In */ fun MutableMethod.getWalkerMethod(context: BytecodeContext, offset: Int): MutableMethod { val newMethod = getInstruction(offset).reference as MethodReference - return context.findClass { classDef -> classDef.type == newMethod.definingClass } - ?.mutableClass - ?.methods - ?.first { method -> MethodUtil.methodSignaturesMatch(method, newMethod) } - ?: throw PatchException("This method can not be walked at offset $offset inside the method $name") + return context.findMethodOrThrow(newMethod.definingClass) { + MethodUtil.methodSignaturesMatch(this, newMethod) + } } -fun MutableClass.addFieldAndInstructions( - context: BytecodeContext, +fun BytecodeContext.addStaticFieldToIntegration( + className: String, methodName: String, fieldName: String, objectClass: String, smaliInstructions: String, - shouldAddConstructor: Boolean + shouldAddConstructor: Boolean = true ) { - val objectCall = "$this->$fieldName:$objectClass" + val mutableClass = findClass { classDef -> classDef.type == className } + ?.mutableClass + ?: throw PatchException("No matching classes found: $className") - methods.single { method -> method.name == methodName }.apply { - staticFields.add( - ImmutableField( - definingClass, - fieldName, - objectClass, - AccessFlags.PUBLIC or AccessFlags.STATIC, - null, - annotations, - null - ).toMutable() - ) + val objectCall = "$mutableClass->$fieldName:$objectClass" - addInstructionsWithLabels( - 0, - """ + mutableClass.apply { + methods.first { method -> method.name == methodName }.apply { + staticFields.add( + ImmutableField( + definingClass, + fieldName, + objectClass, + AccessFlags.PUBLIC or AccessFlags.STATIC, + null, + annotations, + null + ).toMutable() + ) + + addInstructionsWithLabels( + 0, + """ sget-object v0, $objectCall """ + smaliInstructions - ) + ) + } } - if (shouldAddConstructor) { - context.findClass(objectClass)!!.mutableClass.methods - .filter { method -> method.name == "" } - .forEach { mutableMethod -> - mutableMethod.apply { - val initializeIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_DIRECT && getReference()?.name == "" - } - val insertIndex = if (initializeIndex == -1) - 1 - else - initializeIndex + 1 + if (!shouldAddConstructor) return - val initializeRegister = if (initializeIndex == -1) - "p0" - else - "v${getInstruction(initializeIndex).registerC}" - - addInstruction( - insertIndex, - "sput-object $initializeRegister, $objectCall" - ) + findMethodsOrThrow(objectClass) + .filter { method -> MethodUtil.isConstructor(method) } + .forEach { mutableMethod -> + mutableMethod.apply { + val initializeIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_DIRECT && + getReference()?.name == "" } + val insertIndex = if (initializeIndex == -1) + 1 + else + initializeIndex + 1 + + val initializeRegister = if (initializeIndex == -1) + "p0" + else + "v${getInstruction(initializeIndex).registerC}" + + addInstruction( + insertIndex, + "sput-object $initializeRegister, $objectCall" + ) } + } +} + +fun BytecodeContext.findMethodOrThrow( + reference: String, + methodPredicate: Method.() -> Boolean = { MethodUtil.isConstructor(this) } +) = findMethodsOrThrow(reference).first(methodPredicate) + +fun BytecodeContext.findMethodsOrThrow(reference: String): MutableSet { + val methods = + findClass { classDef -> classDef.type == reference } + ?.mutableClass + ?.methods + + if (methods != null) { + return methods + } else { + throw PatchException("No matching methods found in: $reference") } } fun BytecodeContext.updatePatchStatus( className: String, methodName: String -) { - this.classes.forEach { classDef -> - if (classDef.type.endsWith(className)) { - val patchStatusMethod = - this.proxy(classDef).mutableClass.methods.first { it.name == methodName } - - patchStatusMethod.replaceInstruction( - 0, - "const/4 v0, 0x1" - ) - } - } -} +) = findMethodOrThrow(className) { name == methodName } + .replaceInstruction( + 0, + "const/4 v0, 0x1" + ) /** * Return the resolved methods of [MethodFingerprint]s early. @@ -571,7 +586,7 @@ fun List.returnEarly(bool: Boolean = false) { return v0 """ - else -> throw Exception("This case should never happen.") + else -> throw PatchException("This case should never happen: ${fingerprint.javaClass.simpleName}") } result.mutableMethod.addInstructions(0, stringInstructions)