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 package app.revanced.patches.youtube.shorts.startupshortsreset
import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.or import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags 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", name = "userWasInShortsABConfigFingerprint",
returnType = "V", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
strings = listOf("Failed to get offline response: "), returnType = "Z",
customFingerprint = { method, _ -> literals = listOf(45358360L)
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"),
) )
/** /**

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.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch 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.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.extension.Constants.SHORTS_CLASS_DESCRIPTOR 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.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.is_20_02_or_greater
import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.playservice.versionCheckPatch
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference 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.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstStringInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction 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.OneRegisterInstruction
@ -42,50 +36,19 @@ val resumingShortsOnStartupPatch = bytecodePatch(
execute { execute {
fun MutableMethod.hookUserWasInShortsABConfig(startIndex: Int) { userWasInShortsConfigFingerprint
val walkerIndex = implementation!!.instructions.let { .methodOrThrow()
val subListIndex = .addInstructionsWithLabels(
it.subList(startIndex, startIndex + 20).indexOfFirst { instruction -> 0, """
val reference = instruction.getReference<MethodReference>() invoke-static {}, $SHORTS_CLASS_DESCRIPTOR->disableResumingStartupShortsPlayer()Z
instruction.opcode == Opcode.INVOKE_VIRTUAL && move-result v0
reference?.returnType == "Z" && if-eqz v0, :show
reference.definingClass != "Lj${'$'}/util/Optional;" && const/4 v0, 0x0
reference.parameterTypes.isEmpty() return v0
} :show
if (subListIndex < 0) nop
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)
}
}
if (is_20_02_or_greater) { if (is_20_02_or_greater) {
userWasInShortsAlternativeFingerprint.matchOrThrow().let { userWasInShortsAlternativeFingerprint.matchOrThrow().let {