mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-05 00:54:32 +02:00
feat(YouTube): add support version 19.23.40
, drop support version 19.20.35
, 19.21.40
This commit is contained in:
parent
7a0b3033bb
commit
b99c6218f7
@ -7,6 +7,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackManagerFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.BackgroundPlaybackSettingsFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.KidsBackgroundPlaybackPolicyControllerFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.KidsBackgroundPlaybackPolicyControllerParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.fingerprints.PiPControllerFingerprint
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
|
||||
@ -31,7 +32,7 @@ object BackgroundPlaybackPatch : BaseBytecodePatch(
|
||||
fingerprints = setOf(
|
||||
BackgroundPlaybackManagerFingerprint,
|
||||
BackgroundPlaybackSettingsFingerprint,
|
||||
KidsBackgroundPlaybackPolicyControllerFingerprint,
|
||||
KidsBackgroundPlaybackPolicyControllerParentFingerprint,
|
||||
PiPControllerFingerprint
|
||||
)
|
||||
) {
|
||||
@ -66,6 +67,10 @@ object BackgroundPlaybackPatch : BaseBytecodePatch(
|
||||
}
|
||||
|
||||
// Force allowing background play for videos labeled for kids.
|
||||
KidsBackgroundPlaybackPolicyControllerFingerprint.resolve(
|
||||
context,
|
||||
KidsBackgroundPlaybackPolicyControllerParentFingerprint.resultOrThrow().classDef
|
||||
)
|
||||
KidsBackgroundPlaybackPolicyControllerFingerprint.resultOrThrow().mutableMethod.addInstruction(
|
||||
0,
|
||||
"return-void"
|
||||
|
@ -3,40 +3,10 @@ package app.revanced.patches.youtube.misc.backgroundplayback.fingerprints
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.fingerprint.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object KidsBackgroundPlaybackPolicyControllerFingerprint : LiteralValueFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("I", "L", "L"),
|
||||
opcodes = listOf(
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.IGET,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ,
|
||||
Opcode.GOTO,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NE,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NE,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_NE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_EQ,
|
||||
Opcode.GOTO,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
literalSupplier = { 5 }
|
||||
)
|
||||
|
@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.youtube.misc.backgroundplayback.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
internal object KidsBackgroundPlaybackPolicyControllerParentFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
parameters = listOf("Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.indexOfFirstInstruction {
|
||||
opcode == Opcode.SGET_OBJECT
|
||||
&& getReference<FieldReference>()?.name == "miniplayerRenderer"
|
||||
} >= 0
|
||||
}
|
||||
)
|
@ -13,8 +13,7 @@ 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 that supports the 'Restore old seekbar thumbnails' setting.
|
||||
"19.20.35", // This is the last version that play icon in the Miniplayer is not giant.
|
||||
"19.21.40", // This is the latest version supported by the RVX patch.
|
||||
"19.23.40", // This is the latest version supported by the RVX patch.
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -8,6 +8,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
||||
internal object InitializeButtonsFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "V",
|
||||
parameters = emptyList(),
|
||||
literalSupplier = { ImageOnlyTab }
|
||||
)
|
@ -97,6 +97,8 @@ object SettingsPatch : BaseResourcePatch(
|
||||
internal var upward1849 = false
|
||||
internal var upward1902 = false
|
||||
internal var upward1912 = false
|
||||
internal var upward1920 = false
|
||||
internal var upward1923 = false
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
|
||||
@ -285,6 +287,8 @@ object SettingsPatch : BaseResourcePatch(
|
||||
upward1849 = 235000000 <= playServicesVersion
|
||||
upward1902 = 240204000 < playServicesVersion
|
||||
upward1912 = 241302000 <= playServicesVersion
|
||||
upward1920 = 242099000 <= playServicesVersion
|
||||
upward1923 = 242402000 <= playServicesVersion
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -33,9 +33,8 @@ import app.revanced.patches.youtube.video.playback.fingerprints.QualitySetterFin
|
||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getStringInstructionIndex
|
||||
import app.revanced.util.getTargetIndex
|
||||
import app.revanced.util.getTargetIndexOrThrow
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.patch.BaseBytecodePatch
|
||||
import app.revanced.util.resultOrThrow
|
||||
@ -44,6 +43,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
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.util.MethodUtil
|
||||
|
||||
@Suppress("unused")
|
||||
@ -108,6 +108,15 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
||||
// region patch for disable HDR video
|
||||
|
||||
HDRCapabilityFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val stringIndex = getStringInstructionIndex("av1_profile_main_10_hdr_10_plus_supported")
|
||||
val walkerIndex = indexOfFirstInstructionOrThrow(stringIndex) {
|
||||
val reference = getReference<MethodReference>()
|
||||
reference?.parameterTypes == listOf("I", "Landroid/view/Display;")
|
||||
&& reference.returnType == "Z"
|
||||
}
|
||||
|
||||
val walkerMethod = getWalkerMethod(context, walkerIndex)
|
||||
walkerMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0, """
|
||||
invoke-static {}, $INTEGRATIONS_HDR_VIDEO_CLASS_DESCRIPTOR->disableHDRVideo()Z
|
||||
@ -117,6 +126,7 @@ object VideoPlaybackPatch : BaseBytecodePatch(
|
||||
""", ExternalLabel("default", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
package app.revanced.patches.youtube.video.playback.fingerprints
|
||||
|
||||
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object HDRCapabilityFingerprint : MethodReferenceNameFingerprint(
|
||||
returnType = "Z",
|
||||
parameters = listOf("I", "Landroid/view/Display;"),
|
||||
reference = { "getSupportedHdrTypes" }
|
||||
internal object HDRCapabilityFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
strings = listOf(
|
||||
"av1_profile_main_10_hdr_10_plus_supported",
|
||||
"video/av01"
|
||||
)
|
||||
)
|
||||
|
@ -8,6 +8,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint
|
||||
import app.revanced.util.resultOrThrow
|
||||
import java.io.Closeable
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
object PlayerResponseMethodHookPatch :
|
||||
BytecodePatch(setOf(PlayerParameterBuilderFingerprint)),
|
||||
@ -17,57 +18,59 @@ object PlayerResponseMethodHookPatch :
|
||||
// Parameter numbers of the patched method.
|
||||
private var PARAMETER_VIDEO_ID = 1
|
||||
private var PARAMETER_PLAYER_PARAMETER = 3
|
||||
private var PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING = 11
|
||||
private var PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING by Delegates.notNull<Int>()
|
||||
|
||||
private var freeRegister = 0
|
||||
private var shouldApplyNewMethod = false
|
||||
// Registers used to pass the parameters to integrations.
|
||||
private var playerResponseMethodCopyRegisters = false
|
||||
private lateinit var REGISTER_VIDEO_ID : String
|
||||
private lateinit var REGISTER_PLAYER_PARAMETER : String
|
||||
private lateinit var REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING : String
|
||||
|
||||
private lateinit var playerResponseMethod: MutableMethod
|
||||
private var numberOfInstructionsAdded = 0
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
playerResponseMethod = PlayerParameterBuilderFingerprint.resultOrThrow().mutableMethod
|
||||
playerResponseMethod = PlayerParameterBuilderFingerprint
|
||||
.resultOrThrow()
|
||||
.mutableMethod
|
||||
|
||||
playerResponseMethod.apply {
|
||||
freeRegister = implementation!!.registerCount - parameters.size - 2
|
||||
shouldApplyNewMethod = freeRegister > 2
|
||||
if (shouldApplyNewMethod) {
|
||||
PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING = freeRegister
|
||||
PARAMETER_PLAYER_PARAMETER = freeRegister - 2
|
||||
PARAMETER_VIDEO_ID = freeRegister - 3
|
||||
PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING = parameters.size - 2
|
||||
|
||||
// On some app targets the method has too many registers pushing the parameters past v15.
|
||||
// If needed, move the parameters to 4-bit registers so they can be passed to integrations.
|
||||
playerResponseMethodCopyRegisters = implementation!!.registerCount -
|
||||
parameterTypes.size + PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING > 15
|
||||
}
|
||||
|
||||
if (playerResponseMethodCopyRegisters) {
|
||||
REGISTER_VIDEO_ID = "v0"
|
||||
REGISTER_PLAYER_PARAMETER = "v1"
|
||||
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "v2"
|
||||
} else {
|
||||
REGISTER_VIDEO_ID = "p$PARAMETER_VIDEO_ID"
|
||||
REGISTER_PLAYER_PARAMETER = "p$PARAMETER_PLAYER_PARAMETER"
|
||||
REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING = "p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING"
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
fun hookVideoId(hook: Hook) {
|
||||
val instruction =
|
||||
if (shouldApplyNewMethod)
|
||||
"invoke-static {v$PARAMETER_VIDEO_ID, v$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook"
|
||||
else
|
||||
"invoke-static {p$PARAMETER_VIDEO_ID, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook"
|
||||
|
||||
playerResponseMethod.addInstruction(
|
||||
0, instruction
|
||||
0,
|
||||
"invoke-static {$REGISTER_VIDEO_ID, $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook"
|
||||
)
|
||||
numberOfInstructionsAdded++
|
||||
}
|
||||
|
||||
fun hookPlayerParameter(hook: Hook) {
|
||||
val instruction =
|
||||
if (shouldApplyNewMethod)
|
||||
"""
|
||||
invoke-static {v$PARAMETER_VIDEO_ID, v$PARAMETER_PLAYER_PARAMETER, v$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||
move-result-object p3
|
||||
"""
|
||||
else
|
||||
"""
|
||||
invoke-static {p$PARAMETER_VIDEO_ID, p$PARAMETER_PLAYER_PARAMETER, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||
move-result-object p$PARAMETER_PLAYER_PARAMETER
|
||||
"""
|
||||
|
||||
playerResponseMethod.addInstructions(
|
||||
0,
|
||||
instruction
|
||||
0, """
|
||||
invoke-static {$REGISTER_VIDEO_ID, $REGISTER_PLAYER_PARAMETER, $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING}, $hook
|
||||
move-result-object $REGISTER_PLAYER_PARAMETER
|
||||
"""
|
||||
)
|
||||
numberOfInstructionsAdded += 2
|
||||
}
|
||||
|
||||
// Reverse the order in order to preserve insertion order of the hooks.
|
||||
@ -80,14 +83,24 @@ object PlayerResponseMethodHookPatch :
|
||||
videoIdHooks.forEach(::hookVideoId)
|
||||
beforeVideoIdHooks.forEach(::hookPlayerParameter)
|
||||
|
||||
if (shouldApplyNewMethod) {
|
||||
playerResponseMethod.addInstructions(
|
||||
if (playerResponseMethodCopyRegisters) {
|
||||
playerResponseMethod.apply {
|
||||
addInstructions(
|
||||
0, """
|
||||
move-object v$PARAMETER_VIDEO_ID, p1
|
||||
move-object v$PARAMETER_PLAYER_PARAMETER, p3
|
||||
move/from16 v$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING, p11
|
||||
"""
|
||||
move-object/from16 $REGISTER_VIDEO_ID, p$PARAMETER_VIDEO_ID
|
||||
move-object/from16 $REGISTER_PLAYER_PARAMETER, p$PARAMETER_PLAYER_PARAMETER
|
||||
move/from16 $REGISTER_IS_SHORT_AND_OPENING_OR_PLAYING, p$PARAMETER_IS_SHORT_AND_OPENING_OR_PLAYING
|
||||
""",
|
||||
)
|
||||
|
||||
numberOfInstructionsAdded += 3
|
||||
|
||||
// Move the modified register back.
|
||||
addInstruction(
|
||||
numberOfInstructionsAdded,
|
||||
"move-object/from16 p$PARAMETER_PLAYER_PARAMETER, $REGISTER_PLAYER_PARAMETER"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,18 +2,67 @@ package app.revanced.patches.youtube.video.playerresponse.fingerprint
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint.ENDS_WITH_PARAMETER_LIST
|
||||
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint.STARTS_WITH_PARAMETER_LIST
|
||||
import app.revanced.patches.youtube.video.playerresponse.fingerprint.PlayerParameterBuilderFingerprint.parametersEqual
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object PlayerParameterBuilderFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "L",
|
||||
parameters = listOf(
|
||||
// 19.22 and earlier parameters are:
|
||||
// "Ljava/lang/String;", // VideoId.
|
||||
// "[B",
|
||||
// "Ljava/lang/String;", // Player parameters proto buffer.
|
||||
// "Ljava/lang/String;", // PlaylistId.
|
||||
// "I",
|
||||
// "I",
|
||||
// "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"
|
||||
|
||||
// 19.23+ parameters are:
|
||||
// "Ljava/lang/String;", // VideoId.
|
||||
// "[B",
|
||||
// "Ljava/lang/String;", // Player parameters proto buffer.
|
||||
// "Ljava/lang/String;", // PlaylistId.
|
||||
// "I",
|
||||
// "I",
|
||||
// "L",
|
||||
// "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"
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
val parameterTypes = methodDef.parameterTypes
|
||||
val parameterSize = parameterTypes.size
|
||||
if (parameterSize != 13 && parameterSize != 14) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
val startsWithMethodParameterList = parameterTypes.slice(0..5)
|
||||
val endsWithMethodParameterList = parameterTypes.slice(parameterSize - 7..<parameterSize)
|
||||
|
||||
parametersEqual(STARTS_WITH_PARAMETER_LIST, startsWithMethodParameterList)
|
||||
&& parametersEqual(ENDS_WITH_PARAMETER_LIST, endsWithMethodParameterList)
|
||||
}
|
||||
) {
|
||||
val STARTS_WITH_PARAMETER_LIST = listOf(
|
||||
"Ljava/lang/String;", // VideoId.
|
||||
"[B",
|
||||
"Ljava/lang/String;", // Player parameters proto buffer.
|
||||
"Ljava/lang/String;", // PlaylistId.
|
||||
"I",
|
||||
"I",
|
||||
"I"
|
||||
)
|
||||
val ENDS_WITH_PARAMETER_LIST = listOf(
|
||||
"Ljava/util/Set;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/String;",
|
||||
@ -22,4 +71,16 @@ internal object PlayerParameterBuilderFingerprint : MethodFingerprint(
|
||||
"Z",
|
||||
"Z"
|
||||
)
|
||||
)
|
||||
|
||||
fun parametersEqual(
|
||||
parameters1: Iterable<CharSequence>,
|
||||
parameters2: Iterable<CharSequence>
|
||||
): Boolean {
|
||||
if (parameters1.count() != parameters2.count()) return false
|
||||
val iterator1 = parameters1.iterator()
|
||||
parameters2.forEach {
|
||||
if (!it.startsWith(iterator1.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user