From c8cc8c4bdac188affcf2d23bd4548f06cb18c626 Mon Sep 17 00:00:00 2001 From: inotia00 <108592928+inotia00@users.noreply.github.com> Date: Fri, 17 Jan 2025 14:58:20 +0900 Subject: [PATCH] feat(YouTube): Add support version `20.02.38` --- .../youtube/patches/shorts/ShortsPatch.java | 4 + .../patches/shared/litho/LithoFilterPatch.kt | 24 ++++- .../textcomponent/TextComponentPatch.kt | 5 +- .../feed/components/FeedComponentsPatch.kt | 56 ++++++----- .../general/components/Fingerprints.kt | 1 - .../components/LayoutComponentsPatch.kt | 22 ++--- .../general/toolbar/ToolBarComponentsPatch.kt | 7 +- .../components/PlayerComponentsPatch.kt | 57 +++++++----- .../youtube/player/fullscreen/Fingerprints.kt | 8 +- .../fullscreen/FullscreenComponentsPatch.kt | 14 +-- .../shorts/startupshortsreset/Fingerprints.kt | 27 +++++- .../ResumingShortsOnStartupPatch.kt | 92 ++++++++++++++----- .../patches/youtube/utils/Fingerprints.kt | 20 ++-- .../youtube/utils/compatibility/Constants.kt | 3 +- .../fullscreen/FullscreenButtonHookPatch.kt | 89 +++++++++++++----- .../playercontrols/PlayerControlsPatch.kt | 12 ++- .../utils/playservice/VersionCheckPatch.kt | 3 + .../youtube/utils/settings/Fingerprints.kt | 2 - .../youtube/utils/settings/SettingsPatch.kt | 31 +++---- .../information/VideoInformationPatch.kt | 12 ++- .../video/playerresponse/Fingerprints.kt | 45 +++++---- .../PlayerResponseMethodHookPatch.kt | 2 +- 22 files changed, 358 insertions(+), 178 deletions(-) diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/shorts/ShortsPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/shorts/ShortsPatch.java index 91f142099..5f799fdba 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/shorts/ShortsPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/shorts/ShortsPatch.java @@ -61,6 +61,10 @@ public class ShortsPatch { return Settings.DISABLE_RESUMING_SHORTS_PLAYER.get(); } + public static boolean disableResumingStartupShortsPlayer(boolean original) { + return !Settings.DISABLE_RESUMING_SHORTS_PLAYER.get() && original; + } + public static boolean enableShortsTimeStamp(boolean original) { return ENABLE_TIME_STAMP || original; } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt index af61831fd..d517732b1 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/litho/LithoFilterPatch.kt @@ -16,6 +16,7 @@ import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstruction import app.revanced.util.indexOfFirstStringInstructionOrThrow import app.revanced.util.or import com.android.tools.smali.dexlib2.AccessFlags @@ -27,6 +28,7 @@ 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.iface.reference.TypeReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.util.MethodUtil @@ -42,6 +44,8 @@ private var filterCount = 0 internal lateinit var addLithoFilter: (String) -> Unit private set +internal var emptyComponentLabel = "" + val lithoFilterPatch = bytecodePatch( description = "lithoFilterPatch", ) { @@ -73,6 +77,8 @@ val lithoFilterPatch = bytecodePatch( return-object v0 """ + emptyComponentLabel = label + Pair(this, label) } } @@ -121,17 +127,25 @@ val lithoFilterPatch = bytecodePatch( val stringBuilderRegister = getInstruction(stringBuilderIndex).registerA - val emptyStringIndex = indexOfFirstStringInstructionOrThrow("") + val emptyStringIndex = indexOfFirstStringInstruction("") + val relativeIndex = if (emptyStringIndex > -1) { + emptyStringIndex + } else { + val separatorIndex = indexOfFirstStringInstructionOrThrow("|") + indexOfFirstInstructionOrThrow(separatorIndex) { + opcode == Opcode.NEW_INSTANCE && + getReference()?.type == "Ljava/lang/StringBuilder;" + } + } + val identifierRegister = getInstruction( - indexOfFirstInstructionReversedOrThrow(emptyStringIndex) { + indexOfFirstInstructionReversedOrThrow(relativeIndex) { opcode == Opcode.IPUT_OBJECT && getReference()?.type == "Ljava/lang/String;" } ).registerA val objectRegister = getInstruction( - indexOfFirstInstructionOrThrow(emptyStringIndex) { - opcode == Opcode.INVOKE_VIRTUAL - } + indexOfFirstInstructionOrThrow(relativeIndex, Opcode.INVOKE_VIRTUAL) ).registerC val insertIndex = stringBuilderIndex + 1 diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/textcomponent/TextComponentPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/textcomponent/TextComponentPatch.kt index 6b04a1689..93347f20a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/textcomponent/TextComponentPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/textcomponent/TextComponentPatch.kt @@ -16,6 +16,7 @@ import app.revanced.util.indexOfFirstInstruction import app.revanced.util.indexOfFirstInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction import com.android.tools.smali.dexlib2.iface.reference.FieldReference @@ -40,11 +41,11 @@ val textComponentPatch = bytecodePatch( spannedIndex = indexOfSpannableStringInstruction(this) spannedRegister = getInstruction(spannedIndex).registerC spannedContextRegister = - getInstruction(0).registerA + getInstruction(spannedIndex + 1).registerA replaceInstruction( spannedIndex, - "nop" + "move-object/from16 v$spannedContextRegister, p0" ) addInstruction( ++spannedIndex, diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt index fa99e6c4b..3f6afead3 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/feed/components/FeedComponentsPatch.kt @@ -10,6 +10,7 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.litho.addLithoFilter +import app.revanced.patches.shared.litho.emptyComponentLabel import app.revanced.patches.shared.mainactivity.onCreateMethod import app.revanced.patches.youtube.utils.bottomsheet.bottomSheetHookPatch import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE @@ -21,6 +22,9 @@ import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch import app.revanced.patches.youtube.utils.navigation.navigationBarHookPatch import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_FEED_COMPONENTS import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch +import app.revanced.patches.youtube.utils.playservice.is_18_34_or_greater +import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.bar import app.revanced.patches.youtube.utils.resourceid.captionToggleContainer import app.revanced.patches.youtube.utils.resourceid.channelListSubMenu @@ -78,6 +82,7 @@ val feedComponentsPatch = bytecodePatch( sharedResourceIdPatch, settingsPatch, bottomSheetHookPatch, + versionCheckPatch, ) execute { @@ -223,19 +228,22 @@ val feedComponentsPatch = bytecodePatch( // region patch for hide subscriptions channel section for tablet - arrayOf( - channelListSubMenuTabletFingerprint, - channelListSubMenuTabletSyntheticFingerprint - ).forEach { fingerprint -> - fingerprint.methodOrThrow().apply { - addInstructionsWithLabels( - 0, """ - invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z - move-result v0 - if-eqz v0, :show - return-void - """, ExternalLabel("show", getInstruction(0)) - ) + // Integrated as a litho component since YouTube 20.02. + if (!is_20_02_or_greater) { + arrayOf( + channelListSubMenuTabletFingerprint, + channelListSubMenuTabletSyntheticFingerprint + ).forEach { fingerprint -> + fingerprint.methodOrThrow().apply { + addInstructionsWithLabels( + 0, """ + invoke-static {}, $FEED_CLASS_DESCRIPTOR->hideSubscriptionsChannelSection()Z + move-result v0 + if-eqz v0, :show + return-void + """, ExternalLabel("show", getInstruction(0)) + ) + } } } @@ -287,29 +295,27 @@ val feedComponentsPatch = bytecodePatch( it.method.apply { val freeRegister = implementation!!.registerCount - parameters.size - 2 val insertIndex = indexOfFirstInstructionOrThrow { - val reference = ((this as? ReferenceInstruction)?.reference as? MethodReference) + val reference = getReference() reference?.parameterTypes?.size == 1 && reference.parameterTypes.first() == "[B" && reference.returnType.startsWith("L") } - val objectIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_OBJECT) + val objectOpcode = if (is_18_34_or_greater) + Opcode.IGET_OBJECT + else + Opcode.MOVE_OBJECT + val objectIndex = indexOfFirstInstructionReversedOrThrow(insertIndex, objectOpcode) val objectRegister = getInstruction(objectIndex).registerA - val jumpIndex = it.patternMatch!!.startIndex - addInstructionsWithLabels( insertIndex, """ - invoke-static {v$objectRegister, v$freeRegister}, $FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z + invoke-static {v$objectRegister, p3}, $FEED_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z move-result v$freeRegister - if-nez v$freeRegister, :filter - """, ExternalLabel("filter", getInstruction(jumpIndex)) - ) - - addInstruction( - 0, - "move-object/from16 v$freeRegister, p3" + if-eqz v$freeRegister, :ignore + """ + emptyComponentLabel, + ExternalLabel("ignore", getInstruction(insertIndex)) ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/Fingerprints.kt index 0acbf1fa6..76355a112 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/Fingerprints.kt @@ -87,7 +87,6 @@ internal val floatingMicrophoneFingerprint = legacyFingerprint( opcodes = listOf( Opcode.IGET_BOOLEAN, Opcode.IF_EQZ, - Opcode.RETURN_VOID ), literals = listOf(fab), ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt index 05b29167a..e5a06857b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/components/LayoutComponentsPatch.kt @@ -20,6 +20,7 @@ import app.revanced.patches.youtube.utils.patch.PatchList.HIDE_LAYOUT_COMPONENTS import app.revanced.patches.youtube.utils.playservice.is_19_25_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.accountSwitcherAccessibility +import app.revanced.patches.youtube.utils.resourceid.fab import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference import app.revanced.patches.youtube.utils.settings.settingsPatch @@ -154,18 +155,17 @@ val layoutComponentsPatch = bytecodePatch( // region patch for hide floating microphone - floatingMicrophoneFingerprint.matchOrThrow().let { - it.method.apply { - val insertIndex = it.patternMatch!!.startIndex - val register = getInstruction(insertIndex).registerA + floatingMicrophoneFingerprint.methodOrThrow().apply { + val literalIndex = indexOfFirstLiteralInstructionOrThrow(fab) + val booleanIndex = indexOfFirstInstructionOrThrow(literalIndex, Opcode.IGET_BOOLEAN) + val insertRegister = getInstruction(booleanIndex).registerA - addInstructions( - insertIndex + 1, """ - invoke-static {v$register}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z - move-result v$register - """ - ) - } + addInstructions( + booleanIndex + 1, """ + invoke-static {v$insertRegister}, $GENERAL_CLASS_DESCRIPTOR->hideFloatingMicrophone(Z)Z + move-result v$insertRegister + """ + ) } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt index 46233d174..2d50bbb25 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/general/toolbar/ToolBarComponentsPatch.kt @@ -15,6 +15,7 @@ import app.revanced.patches.youtube.utils.castbutton.hookToolBarCastButton import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.extension.Constants.GENERAL_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.patch.PatchList.TOOLBAR_COMPONENTS +import app.revanced.patches.youtube.utils.playservice.is_19_46_or_greater import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.actionBarRingoBackground import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch @@ -265,7 +266,11 @@ val toolBarComponentsPatch = bytecodePatch( // region patch for hide search term thumbnail createSearchSuggestionsFingerprint.methodOrThrow().apply { - val relativeIndex = indexOfFirstLiteralInstructionOrThrow(40L) + val literal = if (is_19_46_or_greater) + 32L + else + 40L + val relativeIndex = indexOfFirstLiteralInstructionOrThrow(literal) val replaceIndex = indexOfFirstInstructionReversedOrThrow(relativeIndex) { opcode == Opcode.INVOKE_VIRTUAL && getReference()?.toString() == "Landroid/widget/ImageView;->setVisibility(I)V" diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt index 3934b2277..029818d01 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/components/PlayerComponentsPatch.kt @@ -23,6 +23,8 @@ import app.revanced.patches.youtube.utils.extension.Constants.SPANS_PATH import app.revanced.patches.youtube.utils.fix.suggestedvideoendscreen.suggestedVideoEndScreenPatch import app.revanced.patches.youtube.utils.patch.PatchList.PLAYER_COMPONENTS import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch +import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.darkBackground import app.revanced.patches.youtube.utils.resourceid.fadeDurationFast import app.revanced.patches.youtube.utils.resourceid.scrimOverlay @@ -278,9 +280,15 @@ val playerComponentsPatch = bytecodePatch( speedOverlayPatch, suggestedVideoEndScreenPatch, videoInformationPatch, + versionCheckPatch, ) execute { + var settingArray = arrayOf( + "PREFERENCE_SCREEN: PLAYER", + "SETTINGS: PLAYER_COMPONENTS" + ) + fun MutableMethod.getAllLiteralComponent( startIndex: Int, endIndex: Int @@ -563,30 +571,34 @@ val playerComponentsPatch = bytecodePatch( ) } - youtubeControlsOverlayFingerprint.methodOrThrow().apply { - val insertIndex = - indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub) - val insertRegister = getInstruction(insertIndex).registerA + if (!is_20_02_or_greater) { + youtubeControlsOverlayFingerprint.methodOrThrow().apply { + val insertIndex = + indexOfFirstLiteralInstructionOrThrow(seekUndoEduOverlayStub) + val insertRegister = getInstruction(insertIndex).registerA - val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "setOnClickListener" - } - val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1) + val onClickListenerIndex = indexOfFirstInstructionOrThrow(insertIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setOnClickListener" + } + val constComponent = getFirstLiteralComponent(insertIndex, onClickListenerIndex - 1) - if (constComponent.isNotEmpty()) { - addInstruction( - onClickListenerIndex + 2, - constComponent + if (constComponent.isNotEmpty()) { + addInstruction( + onClickListenerIndex + 2, + constComponent + ) + } + addInstructionsWithLabels( + insertIndex, """ + invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekUndoMessage()Z + move-result v$insertRegister + if-nez v$insertRegister, :default + """, ExternalLabel("default", getInstruction(onClickListenerIndex + 1)) ) + + settingArray += "SETTINGS: HIDE_SEEK_UNDO_MESSAGE" } - addInstructionsWithLabels( - insertIndex, """ - invoke-static {}, $PLAYER_CLASS_DESCRIPTOR->hideSeekUndoMessage()Z - move-result v$insertRegister - if-nez v$insertRegister, :default - """, ExternalLabel("default", getInstruction(onClickListenerIndex + 1)) - ) } // endregion @@ -652,10 +664,7 @@ val playerComponentsPatch = bytecodePatch( // region add settings addPreference( - arrayOf( - "PREFERENCE_SCREEN: PLAYER", - "SETTINGS: PLAYER_COMPONENTS" - ), + settingArray, PLAYER_COMPONENTS ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/Fingerprints.kt index f65a4b917..bda5fdde7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/Fingerprints.kt @@ -7,6 +7,7 @@ import app.revanced.patches.youtube.utils.resourceid.quickActionsElementContaine import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.or import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.util.MethodUtil internal val broadcastReceiverFingerprint = legacyFingerprint( name = "broadcastReceiverFingerprint", @@ -45,12 +46,15 @@ internal val playerTitleViewFingerprint = legacyFingerprint( literals = listOf(playerVideoTitleView), ) -internal val quickActionsElementFingerprint = legacyFingerprint( - name = "quickActionsElementFingerprint", +internal val quickActionsElementSyntheticFingerprint = legacyFingerprint( + name = "quickActionsElementSyntheticFingerprint", returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Landroid/view/View;"), literals = listOf(quickActionsElementContainer), + customFingerprint = { _, classDef -> + AccessFlags.SYNTHETIC.isSet(classDef.accessFlags) + } ) internal val relatedEndScreenResultsFingerprint = legacyFingerprint( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt index 21f315edc..2a56b37c6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/player/fullscreen/FullscreenComponentsPatch.kt @@ -19,6 +19,7 @@ import app.revanced.patches.youtube.utils.extension.Constants.PATCH_STATUS_CLASS import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.extension.Constants.PLAYER_PATH import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch +import app.revanced.patches.youtube.utils.indexOfFocusableInTouchModeInstruction import app.revanced.patches.youtube.utils.layoutConstructorFingerprint import app.revanced.patches.youtube.utils.mainactivity.mainActivityResolvePatch import app.revanced.patches.youtube.utils.patch.PatchList.FULLSCREEN_COMPONENTS @@ -101,7 +102,6 @@ val fullscreenComponentsPatch = bytecodePatch( "invoke-static {v$targetRegister}, " + "$PLAYER_CLASS_DESCRIPTOR->disableEngagementPanels(Landroidx/coordinatorlayout/widget/CoordinatorLayout;)V" ) - } playerTitleViewFingerprint.methodOrThrow().apply { @@ -190,7 +190,7 @@ val fullscreenComponentsPatch = bytecodePatch( // region patch for quick actions - quickActionsElementFingerprint.methodOrThrow().apply { + quickActionsElementSyntheticFingerprint.methodOrThrow().apply { val containerCalls = implementation!!.instructions.withIndex() .filter { instruction -> (instruction.value as? WideLiteralInstruction)?.wideLiteral == quickActionsElementContainer @@ -219,11 +219,13 @@ val fullscreenComponentsPatch = bytecodePatch( // region patch for compact control overlay youtubeControlsOverlayFingerprint.methodOrThrow().apply { - val targetIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_VIRTUAL && - getReference()?.name == "setFocusableInTouchMode" + val targetIndex = indexOfFocusableInTouchModeInstruction(this) + val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex) { + val reference = getReference() + opcode == Opcode.INVOKE_STATIC && + reference?.returnType == "Z" && + reference.parameterTypes.size == 1 } - val walkerIndex = indexOfFirstInstructionOrThrow(targetIndex, Opcode.INVOKE_STATIC) val walkerMethod = getWalkerMethod(walkerIndex) walkerMethod.apply { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/Fingerprints.kt index 1ce5d5dde..a8408ede6 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/Fingerprints.kt @@ -10,7 +10,7 @@ import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.reference.MethodReference /** - * This fingerprint is compatible with all YouTube versions after v18.15.40. + * YouTube v18.15.40 ~ YouTube 19.46.42 */ internal val userWasInShortsABConfigFingerprint = legacyFingerprint( name = "userWasInShortsABConfigFingerprint", @@ -27,10 +27,35 @@ internal fun indexOfOptionalInstruction(method: Method) = getReference().toString() == "Lj${'$'}/util/Optional;->of(Ljava/lang/Object;)Lj${'$'}/util/Optional;" } +/** + * YouTube 19.47.53 ~ + */ +internal val userWasInShortsABConfigAlternativeFingerprint = legacyFingerprint( + name = "userWasInShortsABConfigAlternativeFingerprint", + returnType = "V", + parameters = listOf("I"), + opcodes = listOf(Opcode.OR_INT_LIT8), + strings = listOf("alias", "null"), +) + +/** + * ~ YouTube 19.50.42 + */ internal val userWasInShortsFingerprint = legacyFingerprint( name = "userWasInShortsFingerprint", returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("Ljava/lang/Object;"), strings = listOf("Failed to read user_was_in_shorts proto after successful warmup") +) + +/** + * YouTube 20.02.08 ~ + */ +internal val userWasInShortsAlternativeFingerprint = legacyFingerprint( + name = "userWasInShortsAlternativeFingerprint", + returnType = "V", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + parameters = listOf("Ljava/lang/Object;"), + strings = listOf("userIsInShorts: ") ) \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt index ea7fe70ea..bfbc72f85 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/shorts/startupshortsreset/ResumingShortsOnStartupPatch.kt @@ -1,20 +1,28 @@ package app.revanced.patches.youtube.shorts.startupshortsreset +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.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.bytecodePatch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE import app.revanced.patches.youtube.utils.extension.Constants.SHORTS_CLASS_DESCRIPTOR import app.revanced.patches.youtube.utils.patch.PatchList.DISABLE_RESUMING_SHORTS_ON_STARTUP +import app.revanced.patches.youtube.utils.playservice.is_19_46_or_greater +import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference import app.revanced.patches.youtube.utils.settings.settingsPatch +import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow +import app.revanced.util.indexOfFirstInstructionReversedOrThrow +import app.revanced.util.indexOfFirstStringInstructionOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -27,12 +35,14 @@ val resumingShortsOnStartupPatch = bytecodePatch( ) { compatibleWith(COMPATIBLE_PACKAGE) - dependsOn(settingsPatch) + dependsOn( + settingsPatch, + versionCheckPatch, + ) execute { - userWasInShortsABConfigFingerprint.methodOrThrow().apply { - val startIndex = indexOfOptionalInstruction(this) + fun MutableMethod.hookUserWasInShortsABConfig(startIndex: Int) { val walkerIndex = implementation!!.instructions.let { val subListIndex = it.subList(startIndex, startIndex + 20).indexOfFirst { instruction -> @@ -64,29 +74,65 @@ val resumingShortsOnStartupPatch = bytecodePatch( } } - userWasInShortsFingerprint.methodOrThrow().apply { - val listenableInstructionIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_INTERFACE && - getReference()?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && - getReference()?.name == "isDone" + if (is_19_46_or_greater) { + userWasInShortsABConfigAlternativeFingerprint.methodOrThrow().apply { + val stringIndex = indexOfFirstStringInstructionOrThrow("null") + val startIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.OR_INT_LIT8) + hookUserWasInShortsABConfig(startIndex) } - val originalInstructionRegister = - getInstruction(listenableInstructionIndex).registerC - val freeRegister = - getInstruction(listenableInstructionIndex + 1).registerA + } else { + userWasInShortsABConfigFingerprint.methodOrThrow().apply { + val startIndex = indexOfOptionalInstruction(this) + hookUserWasInShortsABConfig(startIndex) + } + } - addInstructionsWithLabels( - listenableInstructionIndex + 1, - """ - invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z - move-result v$freeRegister - if-eqz v$freeRegister, :show - return-void - :show - invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z + if (is_20_02_or_greater) { + userWasInShortsAlternativeFingerprint.matchOrThrow().let { + it.method.apply { + val stringIndex = it.stringMatches!!.first().index + val booleanValueIndex = indexOfFirstInstructionReversedOrThrow(stringIndex) { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "booleanValue" + } + val booleanValueRegister = + getInstruction(booleanValueIndex + 1).registerA + + addInstructions( + booleanValueIndex + 2, """ + invoke-static {v$booleanValueRegister}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer(Z)Z + move-result v$booleanValueRegister + """ + ) + } + } + } else { + userWasInShortsFingerprint.methodOrThrow().apply { + val listenableInstructionIndex = indexOfFirstInstructionOrThrow { + val reference = getReference() + opcode == Opcode.INVOKE_INTERFACE && + reference?.definingClass == "Lcom/google/common/util/concurrent/ListenableFuture;" && + reference.name == "isDone" + } + val originalInstructionRegister = + getInstruction(listenableInstructionIndex).registerC + val freeRegister = + getInstruction(listenableInstructionIndex + 1).registerA + + addInstructionsWithLabels( + listenableInstructionIndex + 1, """ - ) - removeInstruction(listenableInstructionIndex) + invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z + move-result v$freeRegister + if-eqz v$freeRegister, :show + return-void + :show + invoke-interface {v$originalInstructionRegister}, Lcom/google/common/util/concurrent/ListenableFuture;->isDone()Z + """ + ) + removeInstruction(listenableInstructionIndex) + } + } // region add settings diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt index d55486456..89aa98555 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/Fingerprints.kt @@ -27,14 +27,12 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference internal val bottomSheetMenuItemBuilderFingerprint = legacyFingerprint( name = "bottomSheetMenuItemBuilderFingerprint", - accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "L", parameters = listOf("L"), opcodes = listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT + Opcode.IGET, + Opcode.AND_INT_LIT16, + Opcode.IF_EQZ, ), strings = listOf("Text missing for BottomSheetMenuItem."), customFingerprint = { method, _ -> @@ -251,9 +249,19 @@ internal val youtubeControlsOverlayFingerprint = legacyFingerprint( fadeDurationFast, insetOverlayViewLayout, scrimOverlay, - seekUndoEduOverlayStub + // Removed in YouTube 20.02.38+ + // seekUndoEduOverlayStub ), + customFingerprint = { method, _ -> + indexOfFocusableInTouchModeInstruction(method) >= 0 + } ) +internal fun indexOfFocusableInTouchModeInstruction(method: Method) = + method.indexOfFirstInstruction { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "setFocusableInTouchMode" + } + const val PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR = "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;" \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt index 0ac2b447c..50799bc3c 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/compatibility/Constants.kt @@ -15,7 +15,8 @@ internal object Constants { "18.48.39", // This is the last version that do not use Rolling Number. "19.05.36", // This is the last version with the least YouTube experimental flag. "19.16.39", // This is the last version where the 'Restore old seekbar thumbnails' setting works. - "19.44.39", // This is the latest version supported by the RVX patch. + "19.44.39", // This is the last supported version for 2024. + "20.02.38", // This is the latest version supported by the RVX patch. ) ) } \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/fullscreen/FullscreenButtonHookPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/fullscreen/FullscreenButtonHookPatch.kt index 489b38a11..b40668b3f 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/fullscreen/FullscreenButtonHookPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/fullscreen/FullscreenButtonHookPatch.kt @@ -7,56 +7,91 @@ import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.extension.Constants.EXTENSION_PATH import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch +import app.revanced.patches.youtube.utils.playservice.is_20_02_or_greater +import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.util.addStaticFieldToExtension import app.revanced.util.findMethodOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.getReference +import app.revanced.util.getWalkerMethod import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction +import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.TypeReference +import kotlin.collections.mutableListOf private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR = "$EXTENSION_PATH/utils/VideoUtils;" -internal lateinit var enterFullscreenMethod: MutableMethod +internal var enterFullscreenMethods = mutableListOf() val fullscreenButtonHookPatch = bytecodePatch( description = "fullscreenButtonHookPatch" ) { - dependsOn(sharedExtensionPatch) + dependsOn( + sharedExtensionPatch, + versionCheckPatch, + ) execute { - val (referenceClass, fullscreenActionClass) = with( - nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow() - ) { - val targetIndex = indexOfFirstInstructionReversedOrThrow { - opcode == Opcode.INVOKE_DIRECT && - getReference()?.parameterTypes?.size == 2 - } - val targetReference = - getInstruction(targetIndex).reference as MethodReference + fun getParameters(): Pair { + nextGenWatchLayoutFullscreenModeFingerprint.methodOrThrow().apply { + val methodIndex = indexOfFirstInstructionReversedOrThrow { + opcode == Opcode.INVOKE_DIRECT && + getReference()?.parameterTypes?.size == 2 + } + val fieldIndex = + indexOfFirstInstructionReversedOrThrow(methodIndex, Opcode.IGET_OBJECT) + val fullscreenActionClass = + (getInstruction(fieldIndex).reference as FieldReference).type - Pair(targetReference.definingClass, targetReference.parameterTypes[1].toString()) + if (is_20_02_or_greater) { + val setAnimatorListenerIndex = + indexOfFirstInstructionOrThrow(methodIndex, Opcode.INVOKE_VIRTUAL) + getWalkerMethod(setAnimatorListenerIndex).apply { + val addListenerIndex = indexOfFirstInstructionOrThrow { + opcode == Opcode.INVOKE_VIRTUAL && + getReference()?.name == "addListener" + } + val animatorListenerAdapterClass = getInstruction( + indexOfFirstInstructionReversedOrThrow(addListenerIndex, Opcode.NEW_INSTANCE) + ).reference.toString() + return Pair( + findMethodOrThrow(animatorListenerAdapterClass) { parameters.isEmpty() }, + fullscreenActionClass + ) + } + } else { + val animatorListenerClass = + (getInstruction(methodIndex).reference as MethodReference).definingClass + return Pair( + findMethodOrThrow(animatorListenerClass) { parameters == listOf("I") }, + fullscreenActionClass + ) + } + } } + val (animatorListenerMethod, fullscreenActionClass) = getParameters() + val (enterFullscreenReference, exitFullscreenReference, opcodeName) = - with(findMethodOrThrow(referenceClass) { parameters == listOf("I") }) { + with(animatorListenerMethod) { val enterFullscreenIndex = indexOfFirstInstructionOrThrow { val reference = getReference() reference?.returnType == "V" && reference.definingClass == fullscreenActionClass && - reference.parameterTypes.size == 0 + reference.parameterTypes.isEmpty() } val exitFullscreenIndex = indexOfFirstInstructionReversedOrThrow { val reference = getReference() reference?.returnType == "V" && reference.definingClass == fullscreenActionClass && - reference.parameterTypes.size == 0 + reference.parameterTypes.isEmpty() } val enterFullscreenReference = @@ -68,18 +103,28 @@ val fullscreenButtonHookPatch = bytecodePatch( val enterFullscreenClass = (enterFullscreenReference as MethodReference).definingClass - enterFullscreenMethod = if (opcode == Opcode.INVOKE_INTERFACE) { - classes.find { classDef -> classDef.interfaces.contains(enterFullscreenClass) } - ?.let { classDef -> + if (opcode == Opcode.INVOKE_INTERFACE) { + classes.forEach { classDef -> + if (enterFullscreenMethods.size >= 2) + return@forEach + if (!classDef.interfaces.contains(enterFullscreenClass)) + return@forEach + + val enterFullscreenMethod = proxy(classDef) .mutableClass .methods .find { method -> method.name == enterFullscreenReference.name } - } ?: throw PatchException("No matching classes: $enterFullscreenClass") - } else { - findMethodOrThrow(enterFullscreenClass) { - name == enterFullscreenReference.name + ?: throw PatchException("No matching classes: $enterFullscreenClass") + + enterFullscreenMethods.add(enterFullscreenMethod) } + } else { + val enterFullscreenMethod = + findMethodOrThrow(enterFullscreenClass) { + name == enterFullscreenReference.name + } + enterFullscreenMethods.add(enterFullscreenMethod) } Triple( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt index e0e54f204..5dbf43ec9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playercontrols/PlayerControlsPatch.kt @@ -9,7 +9,7 @@ import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.extension.Constants.UTILS_PATH import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch -import app.revanced.patches.youtube.utils.fullscreen.enterFullscreenMethod +import app.revanced.patches.youtube.utils.fullscreen.enterFullscreenMethods import app.revanced.patches.youtube.utils.fullscreen.fullscreenButtonHookPatch import app.revanced.patches.youtube.utils.playerButtonsResourcesFingerprint import app.revanced.patches.youtube.utils.playerButtonsVisibilityFingerprint @@ -122,10 +122,12 @@ private val playerControlsBytecodePatch = bytecodePatch( // Reproduced only in RVX if (is_19_23_or_greater) { - enterFullscreenMethod.addInstruction( - 0, - "invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V" - ) + enterFullscreenMethods.forEach { method -> + method.addInstruction( + 0, + "invoke-static {}, $EXTENSION_PLAYER_CONTROLS_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediately()V" + ) + } } // endregion diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt index f7cdcea1f..d6f71edc7 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/playservice/VersionCheckPatch.kt @@ -51,6 +51,8 @@ var is_19_44_or_greater = false private set var is_19_46_or_greater = false private set +var is_20_02_or_greater = false + private set val versionCheckPatch = resourcePatch( description = "versionCheckPatch", @@ -89,5 +91,6 @@ val versionCheckPatch = resourcePatch( is_19_43_or_greater = 244405000 <= playStoreServicesVersion is_19_44_or_greater = 244505000 <= playStoreServicesVersion is_19_46_or_greater = 244705000 <= playStoreServicesVersion + is_20_02_or_greater = 250299000 <= playStoreServicesVersion } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/Fingerprints.kt index 79bdce50a..b43b9f9eb 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/Fingerprints.kt @@ -2,11 +2,9 @@ package app.revanced.patches.youtube.utils.settings import app.revanced.patches.youtube.utils.resourceid.appearance import app.revanced.util.fingerprint.legacyFingerprint -import com.android.tools.smali.dexlib2.Opcode internal val themeSetterSystemFingerprint = legacyFingerprint( name = "themeSetterSystemFingerprint", returnType = "L", - opcodes = listOf(Opcode.RETURN_OBJECT), literals = listOf(appearance), ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt index 82cf48b41..5a0854b44 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/utils/settings/SettingsPatch.kt @@ -1,12 +1,9 @@ package app.revanced.patches.youtube.utils.settings -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.resourcePatch import app.revanced.patcher.patch.stringOption -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_CLASS_DESCRIPTOR import app.revanced.patches.shared.extension.Constants.EXTENSION_UTILS_PATH import app.revanced.patches.shared.mainactivity.injectConstructorMethodCall @@ -23,11 +20,14 @@ import app.revanced.patches.youtube.utils.patch.PatchList.SETTINGS_FOR_YOUTUBE import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch import app.revanced.util.ResourceGroup +import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.copyResources import app.revanced.util.copyXmlNode -import app.revanced.util.fingerprint.matchOrThrow +import app.revanced.util.findInstructionIndicesReversedOrThrow +import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.removeStringsElements import app.revanced.util.valueOrThrow +import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import org.w3c.dom.Element import java.nio.file.Files @@ -50,23 +50,16 @@ private val settingsBytecodePatch = bytecodePatch( ) execute { - fun MutableMethod.injectCall(index: Int) { - val register = getInstruction(index).registerA - - addInstructions( - index + 1, """ - invoke-static {v$register}, $EXTENSION_THEME_METHOD_DESCRIPTOR - return-object v$register - """ - ) - removeInstruction(index) - } // apply the current theme of the settings page - themeSetterSystemFingerprint.matchOrThrow().let { - it.method.apply { - injectCall(implementation!!.instructions.size - 1) - injectCall(it.patternMatch!!.startIndex) + themeSetterSystemFingerprint.methodOrThrow().apply { + findInstructionIndicesReversedOrThrow(Opcode.RETURN_OBJECT).forEach { index -> + val register = getInstruction(index).registerA + + addInstructionsAtControlFlowLabel( + index, + "invoke-static { v$register }, $EXTENSION_THEME_METHOD_DESCRIPTOR" + ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 288fc190c..3cfdfa63a 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -249,11 +249,13 @@ val videoInformationPatch = bytecodePatch( ) val literalIndex = indexOfFirstLiteralInstructionOrThrow(45368273L) - val walkerIndex = - indexOfFirstInstructionReversedOrThrow( - literalIndex, - Opcode.INVOKE_VIRTUAL_RANGE - ) + val walkerIndex = indexOfFirstInstructionReversedOrThrow(literalIndex) { + val reference = getReference() + (opcode == Opcode.INVOKE_VIRTUAL || opcode == Opcode.INVOKE_VIRTUAL_RANGE) && + reference?.definingClass == definingClass && + reference.parameterTypes.isEmpty() && + reference.returnType == "V" + } videoEndMethod = getWalkerMethod(walkerIndex) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt index 02e4b048f..822f8e6aa 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/playerresponse/Fingerprints.kt @@ -13,20 +13,12 @@ private val PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST = listOf( "I", "I" ) -private val PLAYER_PARAMETER_ENDS_WITH_PARAMETER_LIST = listOf( - "Ljava/util/Set;", - "Ljava/lang/String;", - "Ljava/lang/String;", - "L", - "Z", // Appears to indicate if the video id is being opened or is currently playing. - "Z", - "Z" -) internal val playerParameterBuilderFingerprint = legacyFingerprint( name = "playerParameterBuilderFingerprint", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "L", + strings = listOf("psps"), // 19.22 and earlier parameters are: // "Ljava/lang/String;", // VideoId. // "[B", @@ -60,20 +52,41 @@ internal val playerParameterBuilderFingerprint = legacyFingerprint( customFingerprint = custom@{ method, _ -> val parameterTypes = method.parameterTypes val parameterSize = parameterTypes.size - if (parameterSize != 13 && parameterSize != 14) { + if (parameterSize < 13) { return@custom false } val startsWithMethodParameterList = parameterTypes.slice(0..5) - val endsWithMethodParameterList = parameterTypes.slice(parameterSize - 7..