From 4f4ceab2cc32a38dd3967fd4e81f690330c08f5c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 19 Mar 2023 23:24:31 +0100 Subject: [PATCH] feat(youtube): support version `18.08.37` --- .../autoplay/patch/HideAutoplayButtonPatch.kt | 9 +- .../annotations/PivotBarCompatibility.kt | 5 +- .../CrowdfundingBoxFingerprint.kt | 3 - .../bytecode/patch/CrowdfundingBoxPatch.kt | 25 +++-- .../ReturnYouTubeDislikeCompatibility.kt | 15 +-- .../fingerprints/DislikeFingerprint.kt | 3 - .../fingerprints/LikeFingerprint.kt | 3 - .../fingerprints/RemoveLikeFingerprint.kt | 3 - .../TextComponentConstructorFingerprint.kt | 11 ++ .../fingerprints/TextComponentFingerprint.kt | 8 -- .../TextComponentSpecParentFingerprint.kt | 8 -- .../fingerprints/TextReferenceFingerprint.kt | 14 +++ .../TextReferenceParamFingerprint.kt | 11 ++ .../patch/ReturnYouTubeDislikePatch.kt | 55 +++++---- .../bytecode/patch/SpoofAppVersionPatch.kt | 8 +- ...niPlayerDimensionsCalculatorFingerprint.kt | 2 +- .../MiniPlayerOverrideParentFingerprint.kt | 13 +++ .../patch/TabletMiniPlayerPatch.kt | 38 ++++--- .../FixBackToExitGestureCompatibility.kt | 5 +- .../patch/SpoofSignatureVerificationPatch.kt | 2 +- .../annotations/IntegrationsCompatibility.kt | 5 +- .../fingerprints/InitFingerprint.kt | 2 +- .../ComponentContextParserFingerprint.kt | 7 -- .../EmptyComponentBuilderFingerprint.kt | 1 + .../ReadComponentIdentifierFingerprint.kt | 12 ++ .../litho/filter/patch/LithoFilterPatch.kt | 65 ++++++----- .../fingerprints/IntegrityCheckFingerprint.kt | 10 -- .../patch/bytecode/MicroGBytecodePatch.kt | 4 +- .../fingerprints/ThemeSetterAppFingerprint.kt | 8 +- ...dexMethodClassFieldReferenceFingerprint.kt | 14 +++ ...ideoQualityItemOnClickParentFingerprint.kt | 9 ++ .../VideoQualityReferenceFingerprint.kt | 12 -- .../VideoQualitySetterFingerprint.kt | 5 +- .../VideoUserQualityChangeFingerprint.kt | 20 ---- .../patch/RememberVideoQualityPatch.kt | 105 +++++++++++++----- ...gePlaybackSpeedFragmentStateFingerprint.kt | 8 -- ...nitializePlaybackSpeedValuesFingerprint.kt | 3 +- .../OnPlaybackSpeedItemClickFingerprint.kt | 6 +- .../patch/RememberPlaybackSpeedPatch.kt | 99 ++++++++--------- 39 files changed, 357 insertions(+), 279 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceParamFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ReadComponentIdentifierFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/ChangePlaybackSpeedFragmentStateFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt index cdc013341..2700bbad9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/autoplay/patch/HideAutoplayButtonPatch.kt @@ -6,6 +6,7 @@ import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess @@ -20,6 +21,7 @@ import app.revanced.patches.youtube.layout.buttons.autoplay.fingerprints.LayoutC import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import org.jf.dexlib2.iface.instruction.Instruction +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.WideLiteralInstruction import org.jf.dexlib2.iface.reference.MethodReference @@ -66,12 +68,15 @@ class HideAutoplayButtonPatch : BytecodePatch( val jumpInstruction = layoutGenMethodInstructions[insertIndex + branchIndex] as Instruction + // can be clobbered because this register is overwritten after the injected code + val clobberRegister = (instruction(insertIndex) as OneRegisterInstruction).registerA + addInstructions( insertIndex, """ invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z - move-result v11 - if-eqz v11, :hidden + move-result v$clobberRegister + if-eqz v$clobberRegister, :hidden """, listOf(ExternalLabel("hidden", jumpInstruction)) ) } ?: return LayoutConstructorFingerprint.toErrorResult() diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/pivotbar/shared/annotations/PivotBarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/pivotbar/shared/annotations/PivotBarCompatibility.kt index 6a1a5c71b..64b22133a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/pivotbar/shared/annotations/PivotBarCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/pivotbar/shared/annotations/PivotBarCompatibility.kt @@ -6,14 +6,15 @@ import app.revanced.patcher.annotation.Package @Compatibility( [Package( "com.google.android.youtube", arrayOf( - "17.49.37", + "17.49.37", "18.03.36", "18.03.42", "18.04.35", "18.04.41", "18.05.32", "18.05.35", - "18.05.40" + "18.05.40", + "18.08.37" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt index ef7a8b81b..0ad96367d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt @@ -7,12 +7,9 @@ import org.jf.dexlib2.iface.instruction.WideLiteralInstruction object CrowdfundingBoxFingerprint : MethodFingerprint( opcodes = listOf( - Opcode.CONST_4, - Opcode.CONST, Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, Opcode.IPUT_OBJECT, - Opcode.CONST, ), customFingerprint = { methodDef -> methodDef.implementation?.instructions?.any { instruction -> diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt index 82435026f..94d3b103f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/hide/crowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.hide.crowdfundingbox.bytecode.patch +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version @@ -15,7 +16,7 @@ import app.revanced.patches.youtube.layout.hide.crowdfundingbox.annotations.Crow import app.revanced.patches.youtube.layout.hide.crowdfundingbox.bytecode.fingerprints.CrowdfundingBoxFingerprint import app.revanced.patches.youtube.layout.hide.crowdfundingbox.resource.patch.CrowdfundingBoxResourcePatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction @Patch @DependsOn([IntegrationsPatch::class, CrowdfundingBoxResourcePatch::class]) @@ -29,18 +30,20 @@ class CrowdfundingBoxPatch : BytecodePatch( ) ) { override fun execute(context: BytecodeContext): PatchResult { - val crowdfundingBoxResult = CrowdfundingBoxFingerprint.result!! - val crowdfundingBoxMethod = crowdfundingBoxResult.mutableMethod + CrowdfundingBoxFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.endIndex + val objectRegister = (instruction(insertIndex) as TwoRegisterInstruction).registerA - val moveResultObjectIndex = - crowdfundingBoxResult.scanResult.patternScanResult!!.endIndex - 2 - - crowdfundingBoxMethod.addInstruction( - moveResultObjectIndex + 1, """ - invoke-static {v${(crowdfundingBoxMethod.instruction(moveResultObjectIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V - """ - ) + addInstruction(insertIndex, "invoke-static {v$objectRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR") + } + } ?: return CrowdfundingBoxFingerprint.toErrorResult() return PatchResultSuccess() } + + private companion object { + const val INTEGRATIONS_METHOD_DESCRIPTOR = + "Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V" + } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt index c84dbac0d..d3f7bd41c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt @@ -3,19 +3,6 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations import app.revanced.patcher.annotation.Compatibility import app.revanced.patcher.annotation.Package -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf( - "17.49.37", - "18.03.36", - "18.03.42", - "18.04.35", - "18.04.41", - "18.05.32", - "18.05.35", - "18.05.40" - ) - )] -) +@Compatibility([Package("com.google.android.youtube", arrayOf("18.08.37"))]) @Target(AnnotationTarget.CLASS) internal annotation class ReturnYouTubeDislikeCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt index 81c56995c..63609aff7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt @@ -1,11 +1,8 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags object DislikeFingerprint : MethodFingerprint( "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/dislike") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt index f3d9a8f04..5761a395e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt @@ -1,14 +1,11 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags @FuzzyPatternScanMethod(2) object LikeFingerprint : MethodFingerprint( "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/like") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt index 17b43b252..9c226ccf8 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt @@ -1,11 +1,8 @@ package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints -import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags object RemoveLikeFingerprint : MethodFingerprint( "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, strings = listOf("like/removelike") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt new file mode 100644 index 000000000..ca29b8eee --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentConstructorFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints + + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags + +object TextComponentConstructorFingerprint : MethodFingerprint( + access = AccessFlags.CONSTRUCTOR or AccessFlags.PRIVATE, + strings = listOf("TextComponent") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt deleted file mode 100644 index dadd8e607..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint - -object TextComponentFingerprint : MethodFingerprint( - strings = listOf("com.google.android.apps.youtube.music") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt deleted file mode 100644 index 631ca5f77..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint - -object TextComponentSpecParentFingerprint : MethodFingerprint( - strings = listOf("TextComponentSpec: No converter for extension: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceFingerprint.kt new file mode 100644 index 000000000..763aef752 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints + + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object TextReferenceFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.INVOKE_STATIC_RANGE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_DIRECT, + Opcode.INVOKE_VIRTUAL + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceParamFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceParamFingerprint.kt new file mode 100644 index 000000000..f81420fcb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextReferenceParamFingerprint.kt @@ -0,0 +1,11 @@ +package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object TextReferenceParamFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT_FROM16 // the first occurrence of this instruction uses the register for the text object + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt index 6a63c83d0..b483afa1d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt @@ -25,7 +25,9 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch import org.jf.dexlib2.builder.instruction.BuilderInstruction35c +import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction @Patch @DependsOn( @@ -42,7 +44,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @Version("0.0.1") class ReturnYouTubeDislikePatch : BytecodePatch( listOf( - TextComponentSpecParentFingerprint, + TextComponentConstructorFingerprint, ShortsTextComponentParentFingerprint, LikeFingerprint, DislikeFingerprint, @@ -78,27 +80,37 @@ class ReturnYouTubeDislikePatch : BytecodePatch( // region Hook components - TextComponentFingerprint.also { it.resolve(context, TextComponentSpecParentFingerprint.result!!.classDef) } - .result?.let { - with(it.mutableMethod) { - val createComponentMethod = this + TextReferenceFingerprint.also { + it.resolve( + context, + TextComponentConstructorFingerprint.result!!.classDef + ) + }.result?.let { result -> + val moveTextRefParamInstructionIndex = TextReferenceParamFingerprint.also { + if (!TextReferenceParamFingerprint.resolve(context, result.method, result.classDef)) + return TextReferenceParamFingerprint.toErrorResult() + }.result!!.scanResult.patternScanResult!!.endIndex - val conversionContextParam = 5 - val textRefParam = createComponentMethod.parameters.size - 2 - // Insert index must be 0, otherwise UI does not updated correctly in some situations - // such as switching from full screen or when using previous/next overlay buttons. - val insertIndex = 0 + result.mutableMethod.apply { + val insertIndex = result.scanResult.patternScanResult!!.endIndex - createComponentMethod.addInstructions( - insertIndex, - """ - move-object/from16 v7, p$conversionContextParam - move-object/from16 v8, p$textRefParam - invoke-static {v7, v8}, $INTEGRATIONS_PATCH_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V - """ - ) - } - } ?: return TextComponentFingerprint.toErrorResult() + val atomicReferenceInstruction = (instruction(insertIndex - 1) as FiveRegisterInstruction) + val conversionContextParam = atomicReferenceInstruction.registerC + val textRefParam = (instruction(moveTextRefParamInstructionIndex) as TwoRegisterInstruction).registerA + + // Overwritten after injected code, which is why it can be used. + val clobberRegister = atomicReferenceInstruction.registerD + + addInstructions( + insertIndex, + """ + # required instruction, otherwise register might be out of range + move-object/from16 v$clobberRegister, v$textRefParam + invoke-static {v$clobberRegister, v$conversionContextParam}, $ON_COMPONENT_CREATED_DESCRIPTOR + """ + ) + } + } ?: return TextReferenceFingerprint.toErrorResult() ShortsTextComponentParentFingerprint.result?.let { context @@ -138,6 +150,9 @@ class ReturnYouTubeDislikePatch : BytecodePatch( const val INTEGRATIONS_PATCH_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;" + const val ON_COMPONENT_CREATED_DESCRIPTOR = + "$INTEGRATIONS_PATCH_CLASS_DESCRIPTOR->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V" + private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind) } diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt index 3a3b5c81b..8c071d31a 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/spoofappversion/bytecode/patch/SpoofAppVersionPatch.kt @@ -30,10 +30,6 @@ class SpoofAppVersionPatch : BytecodePatch( SpoofAppVersionFingerprint ) ) { - companion object { - const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofAppVersionPatch" - } - override fun execute(context: BytecodeContext): PatchResult { SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( SwitchPreference( @@ -61,4 +57,8 @@ class SpoofAppVersionPatch : BytecodePatch( return PatchResultSuccess() } + + private companion object { + const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofAppVersionPatch" + } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt index a378eaf65..247655248 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt @@ -7,7 +7,7 @@ import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode -@FuzzyPatternScanMethod(2) // TODO: Find a good threshold value +@FuzzyPatternScanMethod(2) object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.FINAL, diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt new file mode 100644 index 000000000..49a394933 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideParentFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.AccessFlags + + +object MiniPlayerOverrideParentFingerprint : MethodFingerprint( + returnType = "L", + access = AccessFlags.PUBLIC or AccessFlags.STATIC, + parameters = listOf("L"), + strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt index 8c4269ee2..a290173e6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.tabletminiplayer.patch +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version @@ -16,10 +17,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerDimensionsCalculatorFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint +import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.* import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @@ -33,7 +31,8 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction class TabletMiniPlayerPatch : BytecodePatch( listOf( MiniPlayerDimensionsCalculatorFingerprint, - MiniPlayerResponseModelSizeCheckFingerprint + MiniPlayerResponseModelSizeCheckFingerprint, + MiniPlayerOverrideParentFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { @@ -47,33 +46,42 @@ class TabletMiniPlayerPatch : BytecodePatch( ) ) - // first resolve the fingerprints via the parent fingerprint + // First resolve the fingerprints via the parent fingerprint. val miniPlayerClass = MiniPlayerDimensionsCalculatorFingerprint.result!!.classDef /* - * no context parameter method + * No context parameter method. */ MiniPlayerOverrideNoContextFingerprint.resolve(context, miniPlayerClass) val (method, _, parameterRegister) = MiniPlayerOverrideNoContextFingerprint.addProxyCall() - // - 1 means to insert before the return instruction + + // Insert right before the return instruction. val secondInsertIndex = method.implementation!!.instructions.size - 1 - method.insertOverride(secondInsertIndex, parameterRegister /** same register used to return **/) + method.insertOverride( + secondInsertIndex, parameterRegister + /** same register used to return **/ + ) /* - * method with context parameter + * Method with context parameter. */ - MiniPlayerOverrideFingerprint.resolve(context, miniPlayerClass) - val (_, _, _) = MiniPlayerOverrideFingerprint.addProxyCall() + MiniPlayerOverrideParentFingerprint.result?.let { + if (!MiniPlayerOverrideFingerprint.resolve(context, it.classDef)) + return MiniPlayerOverrideFingerprint.toErrorResult() + + MiniPlayerOverrideFingerprint.addProxyCall() + + } ?: return MiniPlayerOverrideParentFingerprint.toErrorResult() /* - * size check return value override + * Size check return value override. */ - val (_, _, _) = MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall() + MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall() return PatchResultSuccess() } - // helper methods + // Helper methods. private companion object { fun MethodFingerprint.addProxyCall(): Triple { val (method, scanIndex, parameterRegister) = this.unwrap() diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt index 7ba4cfcf2..88d68b981 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/backtoexitgesture/annotation/FixBackToExitGestureCompatibility.kt @@ -6,14 +6,15 @@ import app.revanced.patcher.annotation.Package @Compatibility( [Package( "com.google.android.youtube", arrayOf( - "17.49.37", + "17.49.37", "18.03.36", "18.03.42", "18.04.35", "18.04.41", "18.05.32", "18.05.35", - "18.05.40" + "18.05.40", + "18.08.37" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt index a8c48cbd1..d40cf2281 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/fix/playback/patch/SpoofSignatureVerificationPatch.kt @@ -107,7 +107,7 @@ class SpoofSignatureVerificationPatch : BytecodePatch( return PatchResultSuccess() } - companion object { + private companion object { const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/SpoofSignatureVerificationPatch;" } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt index 293035d7e..96fc2e7fc 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt @@ -6,14 +6,15 @@ import app.revanced.patcher.annotation.Package @Compatibility( [Package( "com.google.android.youtube", arrayOf( - "17.49.37", + "17.49.37", "18.03.36", "18.03.42", "18.04.35", "18.04.41", "18.05.32", "18.05.35", - "18.05.40" + "18.05.40", + "18.08.37" ) )] ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt index 730e856c1..be3b5d8b7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt @@ -3,5 +3,5 @@ package app.revanced.patches.youtube.misc.integrations.fingerprints import app.revanced.patches.shared.integrations.patch.AbstractIntegrationsPatch.IntegrationsFingerprint object InitFingerprint : IntegrationsFingerprint( - strings = listOf("Application creation"), + strings = listOf("Application creation", "Application.onCreate"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt index 7f661ac49..a57ae700f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt @@ -5,13 +5,6 @@ import org.jf.dexlib2.Opcode object ComponentContextParserFingerprint : MethodFingerprint( opcodes = listOf( - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_16, Opcode.INVOKE_VIRTUAL, Opcode.IPUT_OBJECT, Opcode.NEW_INSTANCE diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt index 1842275a5..7c77b9f96 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt @@ -5,6 +5,7 @@ import org.jf.dexlib2.Opcode object EmptyComponentBuilderFingerprint : MethodFingerprint( opcodes = listOf( + Opcode.INVOKE_INTERFACE, Opcode.INVOKE_STATIC_RANGE ), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ReadComponentIdentifierFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ReadComponentIdentifierFingerprint.kt new file mode 100644 index 000000000..b78e48af1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ReadComponentIdentifierFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.youtube.misc.litho.filter.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object ReadComponentIdentifierFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.IF_NEZ, + null, + Opcode.MOVE_RESULT_OBJECT // Register stores the component identifier string + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt index 9ea24e433..96dfba82c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt @@ -1,10 +1,12 @@ package app.revanced.patches.youtube.misc.litho.filter.patch +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult @@ -16,12 +18,10 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint +import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ReadComponentIdentifierFingerprint import org.jf.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference @DependsOn([IntegrationsPatch::class]) @Description("Hooks the method which parses the bytes into a ComponentContext to filter components.") @@ -31,33 +31,40 @@ class LithoFilterPatch : BytecodePatch( listOf(ComponentContextParserFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { - ComponentContextParserFingerprint.result?.let { result -> - val builderMethodIndex = EmptyComponentBuilderFingerprint - .also { it.resolve(context, result.mutableMethod, result.mutableClass) } - .let { it.result!!.scanResult.patternScanResult!!.startIndex } - + ComponentContextParserFingerprint.result?.also { + arrayOf(EmptyComponentBuilderFingerprint, ReadComponentIdentifierFingerprint).forEach { fingerprint -> + if (!fingerprint.resolve(context, it.mutableMethod, it.mutableClass)) + return fingerprint.toErrorResult() + } + }?.let { result -> + val builderMethodIndex = EmptyComponentBuilderFingerprint.patternScanEndIndex val emptyComponentFieldIndex = builderMethodIndex + 2 - with(result.mutableMethod) { + result.mutableMethod.apply { val insertHookIndex = result.scanResult.patternScanResult!!.endIndex - val clobberedRegister = (instruction(insertHookIndex - 3) as OneRegisterInstruction).registerA + val builderMethodDescriptor = instruction(builderMethodIndex).descriptor + val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).descriptor + // Register is overwritten right after it is used for this patch, therefore free to clobber. + val clobberedRegister = instruction(insertHookIndex).oneRegister - val builderMethodDescriptor = instruction(builderMethodIndex).toDescriptor() - val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).toDescriptor() + @Suppress("UnnecessaryVariable") + // The register, this patch clobbers, is previously used for the StringBuilder, + // later on a new StringBuilder is instantiated on it. + val stringBuilderRegister = clobberedRegister - val stringBuilderRegister = (instruction(insertHookIndex - 1) as TwoRegisterInstruction).registerA + val identifierRegister = instruction(ReadComponentIdentifierFingerprint.patternScanEndIndex).oneRegister addInstructions( insertHookIndex, // right after setting the component.pathBuilder field, """ - invoke-static {v$stringBuilderRegister, v0}, Lapp/revanced/integrations/patches/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z + invoke-static {v$stringBuilderRegister, v$identifierRegister}, Lapp/revanced/integrations/patches/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z move-result v$clobberedRegister if-eqz v$clobberedRegister, :not_an_ad - move-object/from16 v0, p1 - invoke-static {v0}, $builderMethodDescriptor - move-result-object v0 - iget-object v0, v0, $emptyComponentFieldDescriptor - return-object v0 + move-object/from16 v$clobberedRegister, p1 + invoke-static {v$clobberedRegister}, $builderMethodDescriptor + move-result-object v$clobberedRegister + iget-object v$clobberedRegister, v$clobberedRegister, $emptyComponentFieldDescriptor + return-object v$clobberedRegister """, listOf(ExternalLabel("not_an_ad", instruction(insertHookIndex))) ) @@ -68,14 +75,14 @@ class LithoFilterPatch : BytecodePatch( } private companion object { - fun Instruction.toDescriptor() = when (val reference = (this as? ReferenceInstruction)?.reference) { - is MethodReference -> "${reference.definingClass}->${reference.name}(${ - reference.parameterTypes.joinToString( - "" - ) { it } - })${reference.returnType}" - is FieldReference -> "${reference.definingClass}->${reference.name}:${reference.type}" - else -> throw PatchResultError("Unsupported reference type") - } + val MethodFingerprint.patternScanEndIndex + get() = result!!.scanResult.patternScanResult!!.endIndex + + val Instruction.descriptor + get() = (this as ReferenceInstruction).reference.toString() + + val Instruction.oneRegister + get() = (this as OneRegisterInstruction).registerA + } -} +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt deleted file mode 100644 index f3d41191b..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags - -object IntegrityCheckFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), - strings = listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt index 22b1a65da..72b6135a6 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt @@ -10,8 +10,8 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.shared.fingerprints.WatchWhileActivityFingerprint -import app.revanced.patches.youtube.layout.buttons.cast.patch.HideCastButtonPatch import app.revanced.patches.shared.misc.fix.spoof.patch.ClientSpoofPatch +import app.revanced.patches.youtube.layout.buttons.cast.patch.HideCastButtonPatch import app.revanced.patches.youtube.misc.fix.playback.patch.SpoofSignatureVerificationPatch import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility import app.revanced.patches.youtube.misc.microg.fingerprints.* @@ -34,7 +34,6 @@ import app.revanced.util.microg.MicroGBytecodeHelper @Version("0.0.1") class MicroGBytecodePatch : BytecodePatch( listOf( - IntegrityCheckFingerprint, ServiceCheckFingerprint, GooglePlayUtilityFingerprint, CastDynamiteModuleFingerprint, @@ -59,7 +58,6 @@ class MicroGBytecodePatch : BytecodePatch( REVANCED_PACKAGE_NAME ), listOf( - IntegrityCheckFingerprint, ServiceCheckFingerprint, GooglePlayUtilityFingerprint, CastDynamiteModuleFingerprint, diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt index 01c4c1087..1fceecd38 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt @@ -10,16 +10,16 @@ object ThemeSetterAppFingerprint : MethodFingerprint( AccessFlags.PUBLIC or AccessFlags.STATIC, parameters = listOf("L", "L", "L", "L"), opcodes = listOf( - Opcode.CONST, //target reference + Opcode.CONST, // target reference Opcode.GOTO, - Opcode.CONST, //target reference + Opcode.CONST, // target reference Opcode.INVOKE_DIRECT, Opcode.RETURN_OBJECT, Opcode.NEW_INSTANCE, - Opcode.INVOKE_INTERFACE, + null, // changed from invoke interface to invoke virtual Opcode.MOVE_RESULT_OBJECT, Opcode.SGET_OBJECT, Opcode.IF_NE, - Opcode.CONST, //target reference + Opcode.CONST, // target reference ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt new file mode 100644 index 000000000..896b5de3e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/SetQualityByIndexMethodClassFieldReferenceFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.misc.video.quality.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object SetQualityByIndexMethodClassFieldReferenceFingerprint : MethodFingerprint( + returnType = "V", + parameters = listOf("L"), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.RETURN_VOID + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt new file mode 100644 index 000000000..592c62fc0 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityItemOnClickParentFingerprint.kt @@ -0,0 +1,9 @@ + +package app.revanced.patches.youtube.misc.video.quality.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint + +object VideoQualityItemOnClickParentFingerprint : MethodFingerprint( + "V", + strings = listOf("VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt deleted file mode 100644 index 3ea366f78..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.youtube.misc.video.quality.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -object VideoQualityReferenceFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.IPUT_OBJECT, Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt index db1853c17..9a29d162b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt @@ -9,12 +9,13 @@ import org.jf.dexlib2.Opcode object VideoQualitySetterFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("[L", "I", "I", "Z", "I"), + listOf("[L", "I", "Z"), listOf( Opcode.IF_EQZ, Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL, Opcode.IPUT_BOOLEAN, - ) + ), + strings = listOf("menu_item_video_quality"), ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt deleted file mode 100644 index 2575d5d3d..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ - -package app.revanced.patches.youtube.misc.video.quality.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint - -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -object VideoUserQualityChangeFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L","L","I","J"), - listOf( - Opcode.MOVE, - Opcode.MOVE_WIDE, - Opcode.INVOKE_INTERFACE_RANGE, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt index 416ef3f04..28b382d76 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.misc.video.quality.patch +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version @@ -9,6 +10,7 @@ import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch @@ -17,9 +19,9 @@ import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility -import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualityReferenceFingerprint +import app.revanced.patches.youtube.misc.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint +import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualitySetterFingerprint -import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoUserQualityChangeFingerprint import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.reference.FieldReference @@ -32,14 +34,18 @@ import org.jf.dexlib2.iface.reference.FieldReference @Version("0.0.1") class RememberVideoQualityPatch : BytecodePatch( listOf( - VideoQualitySetterFingerprint + VideoQualitySetterFingerprint, + VideoQualityItemOnClickParentFingerprint ) ) { override fun execute(context: BytecodeContext): PatchResult { SettingsPatch.PreferenceScreen.MISC.addPreferences( SwitchPreference( "revanced_remember_video_quality_last_selected", - StringResource("revanced_remember_video_quality_last_selected_title", "Remember video quality changes"), + StringResource( + "revanced_remember_video_quality_last_selected_title", + "Remember video quality changes" + ), true, StringResource( "revanced_remember_video_quality_last_selected_summary_on", @@ -52,37 +58,80 @@ class RememberVideoQualityPatch : BytecodePatch( ) ) - val setterMethod = VideoQualitySetterFingerprint.result!! + /* + * The following code works by hooking the method which is called when the user selects a video quality + * to remember the last selected video quality. + * + * It also hooks the method which is called when the video quality to set is determined. + * Conveniently, at this point the video quality is overridden to the remembered playback speed. + */ - VideoUserQualityChangeFingerprint.resolve(context, setterMethod.classDef) - val userQualityMethod = VideoUserQualityChangeFingerprint.result!! + VideoIdPatch.injectCall("$INTEGRATIONS_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V") - VideoQualityReferenceFingerprint.resolve(context, setterMethod.classDef) - val qualityFieldReference = - VideoQualityReferenceFingerprint.result!!.method.let { method -> - (method.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference - } + // Inject a call to set the remembered quality once a video loads. + VideoQualitySetterFingerprint.result?.also { + if (!SetQualityByIndexMethodClassFieldReferenceFingerprint.resolve(context, it.classDef)) + return PatchResultError("Could not resolve fingerprint to find setQualityByIndex method") + }?.let { + // This instruction refers to the field with the type that contains the setQualityByIndex method. + val instructions = SetQualityByIndexMethodClassFieldReferenceFingerprint.result!! + .method.implementation!!.instructions - VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->newVideoStarted(Ljava/lang/String;)V") + val getOnItemClickListenerClassReference = + (instructions.elementAt(0) as ReferenceInstruction).reference + val getSetQualityByIndexMethodClassFieldReference = + (instructions.elementAt(1) as ReferenceInstruction).reference - val qIndexMethodName = - context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name + val setQualityByIndexMethodClassFieldReference = + getSetQualityByIndexMethodClassFieldReference as FieldReference - setterMethod.mutableMethod.addInstructions( - 0, - """ - iget-object v0, p0, ${setterMethod.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type} - const-string v1, "$qIndexMethodName" - invoke-static {p1, p2, v0, v1}, Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I - move-result p2 - """, - ) + val setQualityByIndexMethodClass = context.classes + .find { classDef -> classDef.type == setQualityByIndexMethodClassFieldReference.type }!! - userQualityMethod.mutableMethod.addInstruction( - 0, - "invoke-static {p3}, Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->userChangedQuality(I)V" - ) + // Get the name of the setQualityByIndex method. + val setQualityByIndexMethod = setQualityByIndexMethodClass.methods + .find { method -> method.parameterTypes.first() == "I" } + ?: return PatchResultError("Could not find setQualityByIndex method") + it.mutableMethod.addInstructions( + 0, + """ + # Get the object instance to invoke the setQualityByIndex method on. + iget-object v0, p0, $getOnItemClickListenerClassReference + iget-object v0, v0, $getSetQualityByIndexMethodClassFieldReference + + # Get the method name. + const-string v1, "${setQualityByIndexMethod.name}" + + # Set the quality. + # The first parameter is the array list of video qualities. + # The second parameter is the index of the selected quality. + # The register v0 stores the object instance to invoke the setQualityByIndex method on. + # The register v1 stores the name of the setQualityByIndex method. + invoke-static {p1, p2, v0, v1}, $INTEGRATIONS_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I + move-result p2 + """, + ) + } ?: return VideoQualitySetterFingerprint.toErrorResult() + + // Inject a call to remember the selected quality. + VideoQualityItemOnClickParentFingerprint.result?.let { + val onItemClickMethod = it.mutableClass.methods.find { method -> method.name == "onItemClick" } + + onItemClickMethod?.apply { + val listItemIndexParameter = 3 + + addInstruction( + 0, + "invoke-static {p$listItemIndexParameter}, $INTEGRATIONS_CLASS_DESCRIPTOR->userChangedQuality(I)V" + ) + } ?: return PatchResultError("Failed to find onItemClick method") + } ?: return VideoQualityItemOnClickParentFingerprint.toErrorResult() return PatchResultSuccess() } + + private companion object { + const val INTEGRATIONS_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;" + } } diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/ChangePlaybackSpeedFragmentStateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/ChangePlaybackSpeedFragmentStateFingerprint.kt deleted file mode 100644 index cb1aca4f6..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/ChangePlaybackSpeedFragmentStateFingerprint.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.remember.fingerprint - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint - -object ChangePlaybackSpeedFragmentStateFingerprint : MethodFingerprint( - "V", - strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt index 140e243cb..e244a298e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/InitializePlaybackSpeedValuesFingerprint.kt @@ -3,5 +3,6 @@ package app.revanced.patches.youtube.misc.video.speed.remember.fingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint object InitializePlaybackSpeedValuesFingerprint : MethodFingerprint( - parameters = listOf("[L", "I") + parameters = listOf("[L", "I"), + strings = listOf("menu_item_playback_speed") ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/OnPlaybackSpeedItemClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/OnPlaybackSpeedItemClickFingerprint.kt index 059d31783..e92afa1c9 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/OnPlaybackSpeedItemClickFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/fingerprint/OnPlaybackSpeedItemClickFingerprint.kt @@ -6,7 +6,9 @@ import org.jf.dexlib2.Opcode object OnPlaybackSpeedItemClickFingerprint : MethodFingerprint( customFingerprint = { it.name == "onItemClick" }, opcodes = listOf( - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_VIRTUAL, + Opcode.RETURN_VOID ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt index ecd909fc0..ca2260853 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/remember/patch/RememberPlaybackSpeedPatch.kt @@ -8,8 +8,6 @@ import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstruction import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.patch.* import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch @@ -19,12 +17,12 @@ import app.revanced.patches.shared.settings.preference.impl.SwitchPreference import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch import app.revanced.patches.youtube.misc.video.speed.remember.annotation.RememberPlaybackSpeedCompatibility -import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.ChangePlaybackSpeedFragmentStateFingerprint import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.OnPlaybackSpeedItemClickFingerprint import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction +import org.jf.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction @Patch @@ -34,7 +32,10 @@ import org.jf.dexlib2.iface.instruction.ReferenceInstruction @RememberPlaybackSpeedCompatibility @Version("0.0.1") class RememberPlaybackSpeedPatch : BytecodePatch( - listOf(ChangePlaybackSpeedFragmentStateFingerprint) + listOf( + OnPlaybackSpeedItemClickFingerprint, + InitializePlaybackSpeedValuesFingerprint + ) ) { override fun execute(context: BytecodeContext): PatchResult { SettingsPatch.PreferenceScreen.MISC.addPreferences( @@ -56,54 +57,67 @@ class RememberPlaybackSpeedPatch : BytecodePatch( ) ) - context.resolveFingerprints() - VideoIdPatch.injectCall("${INTEGRATIONS_CLASS_DESCRIPTOR}->newVideoLoaded(Ljava/lang/String;)V") + /* + * The following code works by hooking the method which is called when the user selects a playback speed + * to remember the last selected playback speed. + * + * It also hooks the method which is called when the playback speeds are initialized. + * Conveniently, at this point the playback speed is set to the remembered playback speed. + */ + + // Set the remembered playback speed. - InitializePlaybackSpeedValuesFingerprint.result!!.apply { - // Infer everything necessary for setPlaybackSate() + InitializePlaybackSpeedValuesFingerprint.result?.apply { + // Infer everything necessary for calling the method setPlaybackSpeed(). + val instructions = OnPlaybackSpeedItemClickFingerprint.result!!.mutableMethod.implementation!!.instructions + fun getReference(offset: Int = 0, opcode: Opcode) = + instructions[instructions.indexOfFirst { it.opcode == opcode } + offset].reference - val playbackHandlerWrapperFieldReference = - (object : MethodFingerprint(opcodes = listOf(Opcode.IF_EQZ)) {}).apply { - OnPlaybackSpeedItemClickFingerprint.result!!.apply { - resolve( - context, - method, - classDef - ) - } - }.getReference(-1) - val playbackHandlerWrapperImplementorClassReference = OnPlaybackSpeedItemClickFingerprint - .getReference(-1) - val playbackHandlerFieldReference = OnPlaybackSpeedItemClickFingerprint - .getReference() - val setPlaybackSpeedMethodReference = OnPlaybackSpeedItemClickFingerprint - .getReference(1) + val setPlaybackSpeedContainerClassFieldReference = + getReference(-1, Opcode.IF_EQZ) + val setPlaybackSpeedClassFieldReference = + getReference(1, Opcode.IGET) + + val setPlaybackSpeedMethodReference = + getReference(2, Opcode.IGET) + + val onItemClickListenerClassFieldReference = mutableMethod.instruction(0).reference + + // Registers are not used at index 0, so they can be freely used. mutableMethod.addInstructions( 0, """ invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getCurrentPlaybackSpeed()F move-result v0 - # check if the playback speed is not 1.0x + + # Check if the playback speed is not 1.0x. const/high16 v1, 0x3f800000 # 1.0f cmpg-float v1, v0, v1 if-eqz v1, :do_not_override + + # Get the instance of the class which has the container class field below. + iget-object v1, p0, $onItemClickListenerClassFieldReference - # invoke setPlaybackSpeed - iget-object v1, p0, $playbackHandlerWrapperFieldReference - check-cast v1, $playbackHandlerWrapperImplementorClassReference - iget-object v2, v1, $playbackHandlerFieldReference + # Get the container class field. + iget-object v1, v1, $setPlaybackSpeedContainerClassFieldReference + + # Get the field from its class. + iget-object v2, v1, $setPlaybackSpeedClassFieldReference + + # Invoke setPlaybackSpeed on that class. invoke-virtual {v2, v0}, $setPlaybackSpeedMethodReference """.trimIndent(), listOf(ExternalLabel("do_not_override", mutableMethod.instruction(0))) ) - } + } ?: return InitializePlaybackSpeedValuesFingerprint.toErrorResult() // Remember the selected playback speed. - OnPlaybackSpeedItemClickFingerprint.result!!.apply { - val setPlaybackSpeedIndex = scanResult.patternScanResult!!.endIndex + OnPlaybackSpeedItemClickFingerprint.result?.apply { + val setPlaybackSpeedIndex = scanResult.patternScanResult!!.startIndex - 3 + val selectedPlaybackSpeedRegister = (mutableMethod.instruction(setPlaybackSpeedIndex) as FiveRegisterInstruction).registerD @@ -111,8 +125,7 @@ class RememberPlaybackSpeedPatch : BytecodePatch( setPlaybackSpeedIndex, "invoke-static { v$selectedPlaybackSpeedRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->setPlaybackSpeed(F)V" ) - } - + } ?: return OnPlaybackSpeedItemClickFingerprint.toErrorResult() return PatchResultSuccess() } @@ -121,20 +134,6 @@ class RememberPlaybackSpeedPatch : BytecodePatch( const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch;" - fun MethodFingerprint.getReference(offsetFromPatternScanResultStartIndex: Int = 0) = this.result!!.let { - val referenceInstruction = it.mutableMethod - .instruction(it.scanResult.patternScanResult!!.startIndex + offsetFromPatternScanResultStartIndex) as ReferenceInstruction - referenceInstruction.reference.toString() - } - - fun BytecodeContext.resolveFingerprints() { - ChangePlaybackSpeedFragmentStateFingerprint.result?.also { - fun MethodFingerprint.resolve() = resolve(this@resolveFingerprints, it.classDef) - - OnPlaybackSpeedItemClickFingerprint.resolve() - InitializePlaybackSpeedValuesFingerprint.resolve() - - } ?: throw ChangePlaybackSpeedFragmentStateFingerprint.toErrorResult() - } + val Instruction.reference get() = (this as ReferenceInstruction).reference.toString() } -} +} \ No newline at end of file