fix(youtube/spoof-player-parameters): Ambient mode, FilmStrip overlay, Thumbnail preview in SeekBar not working

This commit is contained in:
inotia00
2023-09-25 12:17:19 +09:00
parent 39f5cf9740
commit 4eead50c70
7 changed files with 90 additions and 61 deletions

View File

@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
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.Opcode
object ProtobufParameterBuilderFingerprint : MethodFingerprint( object PlayerParameterBuilderFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L", returnType = "L",
parameters = listOf( parameters = listOf(

View File

@ -0,0 +1,23 @@
package app.revanced.patches.youtube.utils.fix.parameter.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.util.bytecode.isWideLiteralExists
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object PlayerResponseModelImplFingerprint : MethodFingerprint(
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.RETURN_OBJECT,
Opcode.CONST_4,
Opcode.RETURN_OBJECT
),
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/PlayerResponseModelImpl;") && methodDef.isWideLiteralExists(
55735497
)
}
)

View File

@ -1,28 +0,0 @@
package app.revanced.patches.youtube.utils.fix.parameter.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch.Companion.Thumbnail
import app.revanced.util.bytecode.isWideLiteralExists
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
object ScrubbedPreviewLayoutFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
returnType = "V",
parameters = listOf("Landroid/content/Context;", "Landroid/util/AttributeSet;", "I", "I"),
opcodes = listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT, // preview imageview
),
// This resource is used in ~ 40 different locations, but this method has a distinct list of parameters to match to.
customFingerprint = { methodDef, _ -> methodDef.isWideLiteralExists(Thumbnail) }
)

View File

@ -0,0 +1,12 @@
package app.revanced.patches.youtube.utils.fix.parameter.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
object StoryboardRendererSpecFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
returnType = "L",
parameters = listOf("Ljava/lang/String;", "J"),
strings = listOf("\\|"),
)

View File

@ -5,23 +5,26 @@ import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Name
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions 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.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility import app.revanced.patches.youtube.utils.annotations.YouTubeCompatibility
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.ProtobufParameterBuilderFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerParameterBuilderFingerprint
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.ScrubbedPreviewLayoutFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.PlayerResponseModelImplFingerprint
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardRendererSpecFingerprint
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailFingerprint
import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailParentFingerprint import app.revanced.patches.youtube.utils.fix.parameter.fingerprints.StoryboardThumbnailParentFingerprint
import app.revanced.patches.youtube.utils.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.utils.playertype.patch.PlayerTypeHookPatch
import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch import app.revanced.patches.youtube.utils.settings.resource.patch.SettingsPatch
import app.revanced.patches.youtube.utils.videoid.general.patch.VideoIdPatch
import app.revanced.util.integrations.Constants.MISC_PATH import app.revanced.util.integrations.Constants.MISC_PATH
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@Patch @Patch
@Name("Spoof player parameters") @Name("Spoof player parameters")
@ -29,35 +32,42 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@DependsOn( @DependsOn(
[ [
SharedResourceIdPatch::class, SharedResourceIdPatch::class,
PlayerTypeHookPatch::class PlayerTypeHookPatch::class,
VideoIdPatch::class
] ]
) )
@YouTubeCompatibility @YouTubeCompatibility
class SpoofPlayerParameterPatch : BytecodePatch( class SpoofPlayerParameterPatch : BytecodePatch(
listOf( listOf(
ProtobufParameterBuilderFingerprint, PlayerParameterBuilderFingerprint,
ScrubbedPreviewLayoutFingerprint, PlayerResponseModelImplFingerprint,
StoryboardRendererSpecFingerprint,
StoryboardThumbnailParentFingerprint StoryboardThumbnailParentFingerprint
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// hook parameter /**
ProtobufParameterBuilderFingerprint.result?.let { * Hook player parameter
*/
PlayerParameterBuilderFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
val protobufParam = 3 val videoIdRegister = 1
val playerParameterRegister = 3
addInstructions( addInstructions(
0, """ 0, """
invoke-static {p$protobufParam}, $INTEGRATIONS_CLASS_DESCRIPTOR->overridePlayerParameter(Ljava/lang/String;)Ljava/lang/String; invoke-static {p$videoIdRegister, p$playerParameterRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object p$protobufParam move-result-object p$playerParameterRegister
""" """
) )
} }
} ?: throw ProtobufParameterBuilderFingerprint.exception } ?: throw PlayerParameterBuilderFingerprint.exception
// When the player parameter is spoofed in incognito mode, this value will always be false /**
// If this value is true, the timestamp and chapter are shown when tapping the seekbar. * Forces the SeekBar thumbnail preview container to be shown
* I don't think this code is needed anymore
*/
StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef -> StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
StoryboardThumbnailFingerprint.also { StoryboardThumbnailFingerprint.also {
it.resolve( it.resolve(
@ -84,23 +94,39 @@ class SpoofPlayerParameterPatch : BytecodePatch(
} ?: throw StoryboardThumbnailFingerprint.exception } ?: throw StoryboardThumbnailFingerprint.exception
} ?: throw StoryboardThumbnailParentFingerprint.exception } ?: throw StoryboardThumbnailParentFingerprint.exception
// Seekbar thumbnail now show up but are always a blank image. /**
// Additional changes are needed to force the client to generate the thumbnails (assuming it's possible), * Hook StoryBoard Renderer URL
// but for now hide the empty thumbnail. * TODO: Find a way to increase the quality of SeekBar thumbnail previews
ScrubbedPreviewLayoutFingerprint.result?.let { */
PlayerResponseModelImplFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
val endIndex = it.scanResult.patternScanResult!!.endIndex val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
val imageViewFieldName = getInstruction<ReferenceInstruction>(endIndex).reference val getStoryBoardRegister =
getInstruction<OneRegisterInstruction>(getStoryBoardIndex).registerA
addInstructions( addInstructions(
implementation!!.instructions.lastIndex, getStoryBoardIndex, """
""" invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec()Ljava/lang/String;
iget-object v0, p0, $imageViewFieldName # copy imageview field to a register move-result-object v$getStoryBoardRegister
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
""" """
) )
} }
} ?: throw ScrubbedPreviewLayoutFingerprint.exception } ?: throw PlayerResponseModelImplFingerprint.exception
StoryboardRendererSpecFingerprint.result?.let {
it.mutableMethod.apply {
val storyBoardUrlParams = 0
addInstructionsWithLabels(
0, """
if-nez p$storyBoardUrlParams, :ignore
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec()Ljava/lang/String;
move-result-object p$storyBoardUrlParams
""", ExternalLabel("ignore", getInstruction(0))
)
}
} ?: throw StoryboardRendererSpecFingerprint.exception
/** /**
* Add settings * Add settings

View File

@ -71,7 +71,6 @@ class SharedResourceIdPatch : ResourcePatch {
var Scrubbing: Long = -1 var Scrubbing: Long = -1
var SettingsBooleanTimeRangeDialog: Long = -1 var SettingsBooleanTimeRangeDialog: Long = -1
var SuggestedAction: Long = -1 var SuggestedAction: Long = -1
var Thumbnail: Long = -1
var ToolBarPaddingHome: Long = -1 var ToolBarPaddingHome: Long = -1
var ToolTipContentView: Long = -1 var ToolTipContentView: Long = -1
var TotalTime: Long = -1 var TotalTime: Long = -1
@ -149,7 +148,6 @@ class SharedResourceIdPatch : ResourcePatch {
Scrubbing = find(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing") Scrubbing = find(DIMEN, "vertical_touch_offset_to_enter_fine_scrubbing")
SettingsBooleanTimeRangeDialog = find(LAYOUT, "setting_boolean_time_range_dialog") SettingsBooleanTimeRangeDialog = find(LAYOUT, "setting_boolean_time_range_dialog")
SuggestedAction = find(LAYOUT, "suggested_action") SuggestedAction = find(LAYOUT, "suggested_action")
Thumbnail = find(ID, "thumbnail")
ToolBarPaddingHome = find(DIMEN, "toolbar_padding_home_action_up") ToolBarPaddingHome = find(DIMEN, "toolbar_padding_home_action_up")
ToolTipContentView = find(LAYOUT, "tooltip_content_view") ToolTipContentView = find(LAYOUT, "tooltip_content_view")
TotalTime = find(STRING, "total_time") TotalTime = find(STRING, "total_time")

View File

@ -607,11 +607,9 @@ If later turned off, the old UI may remain until clear the app data"</string>
<string name="revanced_spoof_player_parameter_summary">"Spoofs player parameters to prevent playback issues <string name="revanced_spoof_player_parameter_summary">"Spoofs player parameters to prevent playback issues
Known issues Known issues
Ambient mode may not work Enhanced bitrate is not available
Clip cannot be played normally Offline downloads may not work
Downloading videos may not work SeekBar thumbnail preview quality is very low"</string>
• Filmstrip overlay are always hidden
• Seekbar thumbnails are hidden"</string>
<string name="revanced_spoof_player_parameter_title">Spoof player parameter</string> <string name="revanced_spoof_player_parameter_title">Spoof player parameter</string>
<string name="revanced_swipe_controls">Swipe controls</string> <string name="revanced_swipe_controls">Swipe controls</string>
<string name="revanced_swipe_magnitude_threshold_summary">The amount of threshold for swipe to occur</string> <string name="revanced_swipe_magnitude_threshold_summary">The amount of threshold for swipe to occur</string>