From 7623b3ae18718b5057ab85b6ed5c0775b7a697d6 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 30 Nov 2024 19:55:15 +0400 Subject: [PATCH] refactor(YouTube): Change fingerprints to support a wider range of target versions (#4026) --- patches/api/patches.api | 5 +-- .../hide/general/HideLayoutComponentsPatch.kt | 24 +++++++---- .../ReturnYouTubeDislikePatch.kt | 4 +- .../DisableResumingShortsOnStartupPatch.kt | 40 +++++++------------ .../layout/startupshortsreset/Fingerprints.kt | 28 +++---------- .../misc/debugging/EnableDebuggingPatch.kt | 31 ++++++++------ .../misc/playservice/VersionCheckPatch.kt | 3 ++ 7 files changed, 59 insertions(+), 76 deletions(-) diff --git a/patches/api/patches.api b/patches/api/patches.api index 2ba4d9a4e..d920cf745 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -1200,10 +1200,6 @@ public final class app/revanced/patches/youtube/layout/startupshortsreset/Disabl public static final fun getDisableResumingShortsOnStartupPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } -public final class app/revanced/patches/youtube/layout/startupshortsreset/FingerprintsKt { - public static final fun indexOfOptionalInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;)I -} - public final class app/revanced/patches/youtube/layout/tablet/EnableTabletLayoutPatchKt { public static final field EXTENSION_CLASS_DESCRIPTOR Ljava/lang/String; public static final fun getEnableTabletLayoutPatch ()Lapp/revanced/patcher/patch/BytecodePatch; @@ -1329,6 +1325,7 @@ public final class app/revanced/patches/youtube/misc/playservice/VersionCheckPat public static final fun is_19_41_or_greater ()Z public static final fun is_19_43_or_greater ()Z public static final fun is_19_46_or_greater ()Z + public static final fun is_19_47_or_greater ()Z } public final class app/revanced/patches/youtube/misc/privacy/RemoveTrackingQueryParameterPatchKt { diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt index 64fd674ad..0a03da6d9 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/hide/general/HideLayoutComponentsPatch.kt @@ -20,6 +20,8 @@ import app.revanced.patches.shared.misc.settings.preference.* import app.revanced.patches.youtube.misc.litho.filter.addLithoFilter import app.revanced.patches.youtube.misc.litho.filter.lithoFilterPatch import app.revanced.patches.youtube.misc.navigation.navigationBarHookPatch +import app.revanced.patches.youtube.misc.playservice.is_19_47_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.findInstructionIndicesReversedOrThrow @@ -118,6 +120,7 @@ val hideLayoutComponentsPatch = bytecodePatch( addResourcesPatch, hideLayoutComponentsResourcePatch, navigationBarHookPatch, + versionCheckPatch ) compatibleWith( @@ -243,22 +246,27 @@ val hideLayoutComponentsPatch = bytecodePatch( // region Mix playlists - val startIndex = parseElementFromBufferFingerprint.patternMatch!!.startIndex - parseElementFromBufferFingerprint.method.apply { - val freeRegister = "v0" + val startIndex = parseElementFromBufferFingerprint.patternMatch!!.startIndex + // Target code is a mess with a lot of register moves. + // There is no simple way to find a free register for all versions so this is hard coded. + val freeRegister = if (is_19_47_or_greater) 6 else 0 val byteArrayParameter = "p3" val conversionContextRegister = getInstruction(startIndex).registerA val returnEmptyComponentInstruction = instructions.last { it.opcode == Opcode.INVOKE_STATIC } + val returnEmptyComponentRegister = (returnEmptyComponentInstruction as FiveRegisterInstruction).registerC addInstructionsWithLabels( startIndex + 1, """ - invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z - move-result $freeRegister - if-nez $freeRegister, :return_empty_component - const/4 $freeRegister, 0x0 # Restore register, required for 19.16 - """, + invoke-static { v$conversionContextRegister, $byteArrayParameter }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->filterMixPlaylists(Ljava/lang/Object;[B)Z + move-result v$freeRegister + if-eqz v$freeRegister, :show + move-object v$returnEmptyComponentRegister, p1 # Required for 19.47 + goto :return_empty_component + :show + const/4 v$freeRegister, 0x0 # Restore register, required for 19.16 + """, ExternalLabel("return_empty_component", returnEmptyComponentInstruction), ) } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt index bc80fd14f..e78abfca4 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/ReturnYouTubeDislikePatch.kt @@ -125,8 +125,8 @@ val returnYouTubeDislikePatch = bytecodePatch( if (is_19_33_or_greater) { insertIndex = indexOfFirstInstructionOrThrow { - opcode == Opcode.INVOKE_STATIC_RANGE && - getReference()?.returnType == textDataClassType + (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) + && getReference()?.returnType == textDataClassType } tempRegister = getInstruction(insertIndex + 1).registerA diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt index f636d364f..ae0eb263b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/DisableResumingShortsOnStartupPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.youtube.layout.startupshortsreset -import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.all.misc.resources.addResources @@ -49,31 +49,6 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( SwitchPreference("revanced_disable_resuming_shorts_player"), ) - userWasInShortsConfigFingerprint.originalMethod.apply { - val startIndex = indexOfOptionalInstruction(this) - val walkerIndex = indexOfFirstInstructionOrThrow(startIndex) { - val reference = getReference() - opcode == Opcode.INVOKE_VIRTUAL && - reference?.returnType == "Z" && - reference.definingClass != "Lj${'$'}/util/Optional;" && - reference.parameterTypes.isEmpty() - } - - // Presumably a method that processes the ProtoDataStore value (boolean) for the 'user_was_in_shorts' key. - navigate(this).to(walkerIndex).stop().addInstructionsWithLabels( - 0, - """ - invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z - move-result v0 - if-eqz v0, :show - const/4 v0, 0x0 - return v0 - :show - nop - """, - ) - } - userWasInShortsFingerprint.method.apply { val listenableInstructionIndex = indexOfFirstInstructionOrThrow { opcode == Opcode.INVOKE_INTERFACE && @@ -94,5 +69,18 @@ val disableResumingShortsOnStartupPatch = bytecodePatch( """, ) } + + userWasInShortsConfigFingerprint.method.addInstructions( + 0, + """ + invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z + move-result v0 + if-eqz v0, :show + const/4 v0, 0x0 + return v0 + :show + nop + """ + ) } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt index 326ebbe14..1ae9ce7fe 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/Fingerprints.kt @@ -1,13 +1,8 @@ package app.revanced.patches.youtube.layout.startupshortsreset import app.revanced.patcher.fingerprint -import app.revanced.util.getReference -import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.reference.MethodReference -import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference -import com.android.tools.smali.dexlib2.util.MethodUtil internal val userWasInShortsFingerprint = fingerprint { returns("V") @@ -20,22 +15,9 @@ internal val userWasInShortsFingerprint = fingerprint { * 18.15.40+ */ internal val userWasInShortsConfigFingerprint = fingerprint { - returns("V") - strings("Failed to get offline response: ") - custom { method, _ -> - indexOfOptionalInstruction(method) >= 0 + accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) + returns("Z") + literal { + 45358360L } } - -private val optionalOfMethodReference = ImmutableMethodReference( - "Lj${'$'}/util/Optional;", - "of", - listOf("Ljava/lang/Object;"), - "Lj${'$'}/util/Optional;", -) - -fun indexOfOptionalInstruction(method: Method) = method.indexOfFirstInstruction { - val reference = getReference() ?: return@indexOfFirstInstruction false - - MethodUtil.methodSignaturesMatch(reference, optionalOfMethodReference) -} diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt index 55fc04e39..9c0dc3e85 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/EnableDebuggingPatch.kt @@ -8,6 +8,8 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPref import app.revanced.patches.shared.misc.settings.preference.PreferenceScreenPreference.Sorting import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch +import app.revanced.patches.youtube.misc.playservice.is_19_16_or_greater +import app.revanced.patches.youtube.misc.playservice.versionCheckPatch import app.revanced.patches.youtube.misc.settings.PreferenceScreen import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.util.indexOfFirstInstructionOrThrow @@ -25,6 +27,7 @@ val enableDebuggingPatch = bytecodePatch( sharedExtensionPatch, settingsPatch, addResourcesPatch, + versionCheckPatch ) compatibleWith( @@ -91,20 +94,22 @@ val enableDebuggingPatch = bytecodePatch( ) } - experimentalLongFeatureFlagFingerprint.match( - experimentalFeatureFlagParentFingerprint.originalClassDef - ).method.apply { - val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) + if (is_19_16_or_greater) { + experimentalLongFeatureFlagFingerprint.match( + experimentalFeatureFlagParentFingerprint.originalClassDef + ).method.apply { + val insertIndex = indexOfFirstInstructionOrThrow(Opcode.MOVE_RESULT_WIDE) - addInstructions( - insertIndex, - """ - move-result-wide v0 - invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isLongFeatureFlagEnabled(JJJ)J - move-result-wide v0 - return-wide v0 - """ - ) + addInstructions( + insertIndex, + """ + move-result-wide v0 + invoke-static/range { v0 .. v5 }, $EXTENSION_CLASS_DESCRIPTOR->isLongFeatureFlagEnabled(JJJ)J + move-result-wide v0 + return-wide v0 + """ + ) + } } experimentalStringFeatureFlagFingerprint.match( diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt index f989ce16c..e5c233b11 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/playservice/VersionCheckPatch.kt @@ -39,6 +39,8 @@ var is_19_43_or_greater = false private set var is_19_46_or_greater = false private set +var is_19_47_or_greater = false + private set val versionCheckPatch = resourcePatch( description = "Uses the Play Store service version to find the major/minor version of the YouTube target app.", @@ -71,5 +73,6 @@ val versionCheckPatch = resourcePatch( is_19_41_or_greater = 244305000 <= playStoreServicesVersion is_19_43_or_greater = 244405000 <= playStoreServicesVersion is_19_46_or_greater = 244705000 <= playStoreServicesVersion + is_19_47_or_greater = 244799000 <= playStoreServicesVersion } }