From 238bed12519ec61a53b1ee72da467830ef252154 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 19 Sep 2023 06:22:38 +0400 Subject: [PATCH] fix(YouTube): Restore functionality of `Old video quality menu` and `Custom speeds` on tablets (#2999) --- .../CreateBottomSheetFingerprint.kt | 13 ------- .../hook/patch/BottomSheetHookPatch.kt | 39 ------------------- .../patch/BottomSheetHookResourcePatch.kt | 19 --------- .../RecyclerViewTreeObserverFingerprint.kt | 21 ++++++++++ .../hook/patch/RecyclerViewTreeHookPatch.kt | 37 ++++++++++++++++++ .../custom/patch/CustomPlaybackSpeedPatch.kt | 11 +++--- .../patch/OldVideoQualityMenuPatch.kt | 7 ++-- 7 files changed, 67 insertions(+), 80 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/patch/RecyclerViewTreeHookPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt deleted file mode 100644 index c60cbdc6d..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/fingerprints/CreateBottomSheetFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookResourcePatch -import app.revanced.util.patch.LiteralValueFingerprint -import com.android.tools.smali.dexlib2.AccessFlags - -object CreateBottomSheetFingerprint : LiteralValueFingerprint( - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, - parameters = listOf("L"), - returnType = "Landroid/widget/LinearLayout;", - literal = BottomSheetHookResourcePatch.bottomSheetMargins -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt deleted file mode 100644 index 2084360ae..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookPatch.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.youtube.misc.bottomsheet.hook.patch - -import app.revanced.extensions.exception -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.extensions.InstructionExtensions.getInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.bottomsheet.hook.fingerprints.CreateBottomSheetFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction - -@DependsOn([IntegrationsPatch::class, BottomSheetHookResourcePatch::class]) -class BottomSheetHookPatch : BytecodePatch( - listOf(CreateBottomSheetFingerprint) -) { - override fun execute(context: BytecodeContext) { - CreateBottomSheetFingerprint.result?.let { - it.mutableMethod.apply { - val returnLinearLayoutIndex = implementation!!.instructions.lastIndex - val linearLayoutRegister = getInstruction(returnLinearLayoutIndex).registerA - - addHook = { classDescriptor -> - addInstruction( - returnLinearLayoutIndex, - "invoke-static { v$linearLayoutRegister }, " + - "${classDescriptor}->" + - "onFlyoutMenuCreate(Landroid/widget/LinearLayout;)V" - ) - } - } - } ?: throw CreateBottomSheetFingerprint.exception - } - - internal companion object { - internal lateinit var addHook: (String) -> Unit - private set - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt deleted file mode 100644 index 14b434d6a..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/bottomsheet/hook/patch/BottomSheetHookResourcePatch.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.youtube.misc.bottomsheet.hook.patch - -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchException -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch - -@DependsOn([ResourceMappingPatch::class]) -class BottomSheetHookResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext) { - bottomSheetMargins = ResourceMappingPatch.resourceMappings.find { it.name == "bottom_sheet_margins" }?.id - ?: throw PatchException("Could not find resource") - } - - internal companion object { - var bottomSheetMargins = -1L - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt new file mode 100644 index 000000000..89f871962 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/fingerprints/RecyclerViewTreeObserverFingerprint.kt @@ -0,0 +1,21 @@ +package app.revanced.patches.youtube.misc.recyclerviewtree.hook.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +object RecyclerViewTreeObserverFingerprint : MethodFingerprint( + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + opcodes = listOf( + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.IGET_BOOLEAN, + Opcode.IF_NEZ, + Opcode.INVOKE_VIRTUAL_RANGE, + Opcode.MOVE_RESULT_OBJECT + ), + strings = listOf("LithoRVSLCBinder") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/patch/RecyclerViewTreeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/patch/RecyclerViewTreeHookPatch.kt new file mode 100644 index 000000000..f0ddbe70c --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/recyclerviewtree/hook/patch/RecyclerViewTreeHookPatch.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.youtube.misc.recyclerviewtree.hook.patch + +import app.revanced.extensions.exception +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch +import app.revanced.patches.youtube.misc.recyclerviewtree.hook.fingerprints.RecyclerViewTreeObserverFingerprint + +@DependsOn([IntegrationsPatch::class]) +class RecyclerViewTreeHookPatch : BytecodePatch( + listOf(RecyclerViewTreeObserverFingerprint) +) { + override fun execute(context: BytecodeContext) { + + RecyclerViewTreeObserverFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.startIndex + 5 + val recyclerViewParameter = 2 + + addHook = { classDescriptor -> + addInstruction( + insertIndex, + "invoke-static/range { p$recyclerViewParameter .. p$recyclerViewParameter }, $classDescriptor->onFlyoutMenuCreate(Landroid/support/v7/widget/RecyclerView;)V" + ) + } + } + } ?: throw RecyclerViewTreeObserverFingerprint.exception + + } + + internal companion object { + internal lateinit var addHook: (String) -> Unit + private set + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt index befcebc3b..e0f6b5f73 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/custom/patch/CustomPlaybackSpeedPatch.kt @@ -17,7 +17,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMut import app.revanced.patches.shared.settings.preference.impl.InputType import app.revanced.patches.shared.settings.preference.impl.StringResource import app.revanced.patches.shared.settings.preference.impl.TextPreference -import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch +import app.revanced.patches.youtube.misc.recyclerviewtree.hook.patch.RecyclerViewTreeHookPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch @@ -32,7 +32,7 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableField @Name("Custom playback speed") @Description("Adds custom playback speed options.") -@DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, BottomSheetHookPatch::class]) +@DependsOn([IntegrationsPatch::class, LithoFilterPatch::class, SettingsPatch::class, RecyclerViewTreeHookPatch::class]) class CustomPlaybackSpeedPatch : BytecodePatch( listOf( SpeedArrayGeneratorFingerprint, @@ -116,20 +116,19 @@ class CustomPlaybackSpeedPatch : BytecodePatch( val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA - // edit: alternatively this might work by overriding with fixed values such as 0.1x and 10x limiterMethod.replaceInstruction( limiterMinConstIndex, - "sget v$limiterMinConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->minPlaybackSpeed:F" + "const/high16 v$limiterMinConstDestination, 0x0" ) limiterMethod.replaceInstruction( limiterMaxConstIndex, - "sget v$limiterMaxConstDestination, $INTEGRATIONS_CLASS_DESCRIPTOR->maxPlaybackSpeed:F" + "const/high16 v$limiterMaxConstDestination, 0x41200000 # 10.0f" ) // region Force old video quality menu. // This is necessary, because there is no known way of adding custom playback speeds to the new menu. - BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR) + RecyclerViewTreeHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR) // Required to check if the playback speed menu is currently shown. LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt index e10cca26f..3951c9d4d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/videoqualitymenu/patch/OldVideoQualityMenuPatch.kt @@ -8,9 +8,9 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.bottomsheet.hook.patch.BottomSheetHookPatch import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch +import app.revanced.patches.youtube.misc.recyclerviewtree.hook.patch.RecyclerViewTreeHookPatch import app.revanced.patches.youtube.video.videoqualitymenu.annotations.OldVideoQualityMenuCompatibility import app.revanced.patches.youtube.video.videoqualitymenu.fingerprints.VideoQualityMenuViewInflateFingerprint import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -20,7 +20,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction IntegrationsPatch::class, OldVideoQualityMenuResourcePatch::class, LithoFilterPatch::class, - BottomSheetHookPatch::class + RecyclerViewTreeHookPatch::class ]) @Name("Old video quality menu") @Description("Shows the old video quality with the advanced video quality options instead of the new one.") @@ -30,6 +30,7 @@ class OldVideoQualityMenuPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext) { // region Patch for the old type of the video quality menu. + // Only used when spoofing to old app version. VideoQualityMenuViewInflateFingerprint.result?.let { it.mutableMethod.apply { @@ -49,7 +50,7 @@ class OldVideoQualityMenuPatch : BytecodePatch( // region Patch for the new type of the video quality menu. - BottomSheetHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR) + RecyclerViewTreeHookPatch.addHook(INTEGRATIONS_CLASS_DESCRIPTOR) // Required to check if the video quality menu is currently shown in order to click on the "Advanced" item. LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)