feat(YouTube - Disable resuming Shorts on startup): Match with ReVanced

This commit is contained in:
inotia00 2025-04-01 19:01:18 +09:00
parent 22b98336d5
commit 457dbfec6c
2 changed files with 18 additions and 79 deletions

View File

@ -1,41 +1,17 @@
package app.revanced.patches.youtube.shorts.startupshortsreset
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
/**
* YouTube v18.15.40 ~ YouTube 19.46.42
* YouTube v18.15.40+
*/
internal val userWasInShortsABConfigFingerprint = legacyFingerprint(
internal val userWasInShortsConfigFingerprint = legacyFingerprint(
name = "userWasInShortsABConfigFingerprint",
returnType = "V",
strings = listOf("Failed to get offline response: "),
customFingerprint = { method, _ ->
indexOfOptionalInstruction(method) >= 0
}
)
internal fun indexOfOptionalInstruction(method: Method) =
method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC &&
getReference<MethodReference>().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"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
literals = listOf(45358360L)
)
/**

View File

@ -4,14 +4,10 @@ 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
@ -19,10 +15,8 @@ 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
@ -42,50 +36,19 @@ val resumingShortsOnStartupPatch = bytecodePatch(
execute {
fun MutableMethod.hookUserWasInShortsABConfig(startIndex: Int) {
val walkerIndex = implementation!!.instructions.let {
val subListIndex =
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction ->
val reference = instruction.getReference<MethodReference>()
instruction.opcode == Opcode.INVOKE_VIRTUAL &&
reference?.returnType == "Z" &&
reference.definingClass != "Lj${'$'}/util/Optional;" &&
reference.parameterTypes.isEmpty()
}
if (subListIndex < 0)
throw PatchException("subListIndex not found")
startIndex + subListIndex
}
val walkerMethod = getWalkerMethod(walkerIndex)
// This method will only be called for the user being A/B tested.
// Presumably a method that processes the ProtoDataStore value (boolean) for the 'user_was_in_shorts' key.
walkerMethod.apply {
addInstructionsWithLabels(
0, """
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
move-result v0
if-eqz v0, :show
const/4 v0, 0x0
return v0
""", ExternalLabel("show", getInstruction(0))
)
}
}
if (is_19_46_or_greater) {
userWasInShortsABConfigAlternativeFingerprint.methodOrThrow().apply {
val stringIndex = indexOfFirstStringInstructionOrThrow("null")
val startIndex = indexOfFirstInstructionOrThrow(stringIndex, Opcode.OR_INT_LIT8)
hookUserWasInShortsABConfig(startIndex)
}
} else {
userWasInShortsABConfigFingerprint.methodOrThrow().apply {
val startIndex = indexOfOptionalInstruction(this)
hookUserWasInShortsABConfig(startIndex)
}
}
userWasInShortsConfigFingerprint
.methodOrThrow()
.addInstructionsWithLabels(
0, """
invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
move-result v0
if-eqz v0, :show
const/4 v0, 0x0
return v0
:show
nop
"""
)
if (is_20_02_or_greater) {
userWasInShortsAlternativeFingerprint.matchOrThrow().let {