refactor(YouTube): Change fingerprints to support a wider range of target versions (#4026)

This commit is contained in:
LisoUseInAIKyrios 2024-11-30 19:55:15 +04:00 committed by GitHub
parent 1080a68da2
commit 7623b3ae18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 59 additions and 76 deletions

View File

@ -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 {

View File

@ -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<TwoRegisterInstruction>(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),
)
}

View File

@ -125,8 +125,8 @@ val returnYouTubeDislikePatch = bytecodePatch(
if (is_19_33_or_greater) {
insertIndex = indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_STATIC_RANGE &&
getReference<MethodReference>()?.returnType == textDataClassType
(opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE)
&& getReference<MethodReference>()?.returnType == textDataClassType
}
tempRegister = getInstruction<OneRegisterInstruction>(insertIndex + 1).registerA

View File

@ -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<MethodReference>()
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
"""
)
}
}

View File

@ -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<MethodReference>() ?: return@indexOfFirstInstruction false
MethodUtil.methodSignaturesMatch(reference, optionalOfMethodReference)
}

View File

@ -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(

View File

@ -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
}
}