fix(YouTube Music - Spoof streaming data): Sometimes the app crashes when connected to Wi-Fi

This commit is contained in:
inotia00
2025-01-04 19:09:10 +09:00
parent 697a519365
commit 6a9ad25d30
8 changed files with 196 additions and 94 deletions

View File

@ -7,14 +7,14 @@ import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKA
import app.revanced.patches.music.utils.dismiss.dismissQueueHookPatch
import app.revanced.patches.music.utils.extension.Constants.MISC_PATH
import app.revanced.patches.music.utils.patch.PatchList.DISABLE_MUSIC_VIDEO_IN_ALBUM
import app.revanced.patches.music.utils.playservice.is_7_03_or_greater
import app.revanced.patches.music.utils.playservice.versionCheckPatch
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
import app.revanced.patches.music.utils.settings.addSwitchPreference
import app.revanced.patches.music.utils.settings.settingsPatch
import app.revanced.patches.music.video.information.videoIdHook
import app.revanced.patches.music.video.information.videoInformationPatch
import app.revanced.patches.music.video.playerresponse.hookPlayerResponse
import app.revanced.patches.music.video.playerresponse.playerResponseMethodHookPatch
import app.revanced.util.fingerprint.methodOrThrow
private const val EXTENSION_CLASS_DESCRIPTOR =
@ -32,23 +32,14 @@ val albumMusicVideoPatch = bytecodePatch(
settingsPatch,
dismissQueueHookPatch,
videoInformationPatch,
versionCheckPatch,
playerResponseMethodHookPatch,
)
execute {
// region hook player response
val fingerprint = if (is_7_03_or_greater) {
playerParameterBuilderFingerprint
} else {
playerParameterBuilderLegacyFingerprint
}
fingerprint.methodOrThrow().addInstruction(
0,
"invoke-static {p1, p4, p5}, $EXTENSION_CLASS_DESCRIPTOR->newPlayerResponse(Ljava/lang/String;Ljava/lang/String;I)V"
)
hookPlayerResponse("$EXTENSION_CLASS_DESCRIPTOR->newPlayerResponse(Ljava/lang/String;Ljava/lang/String;I)V")
// endregion

View File

@ -3,62 +3,7 @@ package app.revanced.patches.music.misc.album
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* For targets 7.03 and later.
*/
internal val playerParameterBuilderFingerprint = legacyFingerprint(
name = "playerParameterBuilderFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L",
parameters = listOf(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;", // PlaylistId.
"I", // PlaylistIndex.
"I",
"L",
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z",
"Z",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
),
strings = listOf("psps")
)
/**
* For targets 7.02 and earlier.
*/
internal val playerParameterBuilderLegacyFingerprint = legacyFingerprint(
name = "playerParameterBuilderLegacyFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L",
parameters = listOf(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;", // PlaylistId.
"I", // PlaylistIndex.
"I",
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE
)
)
internal val snackBarParentFingerprint = legacyFingerprint(
name = "snackBarParentFingerprint",

View File

@ -9,11 +9,17 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
import app.revanced.patches.music.utils.settings.addSwitchPreference
import app.revanced.patches.music.utils.settings.settingsPatch
import app.revanced.patches.music.video.playerresponse.hookPlayerResponse
import app.revanced.patches.music.video.playerresponse.playerResponseMethodHookPatch
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
import app.revanced.patches.shared.extension.Constants.SPOOF_PATH
import app.revanced.patches.shared.spoof.streamingdata.baseSpoofStreamingDataPatch
import app.revanced.patches.shared.spoof.useragent.baseSpoofUserAgentPatch
import app.revanced.util.findMethodOrThrow
const val EXTENSION_CLASS_DESCRIPTOR =
"$SPOOF_PATH/SpoofStreamingDataPatch;"
@Suppress("unused")
val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
{
@ -22,6 +28,7 @@ val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
dependsOn(
baseSpoofUserAgentPatch(YOUTUBE_MUSIC_PACKAGE_NAME),
settingsPatch,
playerResponseMethodHookPatch,
)
},
{
@ -32,6 +39,11 @@ val spoofStreamingDataPatch = baseSpoofStreamingDataPatch(
"const/4 v0, 0x1"
)
hookPlayerResponse(
"$EXTENSION_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;)V",
true
)
addSwitchPreference(
CategoryType.MISC,
"revanced_spoof_streaming_data",

View File

@ -0,0 +1,61 @@
package app.revanced.patches.music.video.playerresponse
import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
/**
* For targets 7.03 and later.
*/
internal val playerParameterBuilderFingerprint = legacyFingerprint(
name = "playerParameterBuilderFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L",
parameters = listOf(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;", // PlaylistId.
"I", // PlaylistIndex.
"I",
"L",
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z",
"Z",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
),
strings = listOf("psps")
)
/**
* For targets 7.02 and earlier.
*/
internal val playerParameterBuilderLegacyFingerprint = legacyFingerprint(
name = "playerParameterBuilderLegacyFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L",
parameters = listOf(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;", // PlaylistId.
"I", // PlaylistIndex.
"I",
"Ljava/util/Set;",
"Ljava/lang/String;",
"Ljava/lang/String;",
"L",
"Z",
"Z", // Appears to indicate if the video id is being opened or is currently playing.
),
opcodes = listOf(
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE
)
)

View File

@ -0,0 +1,40 @@
package app.revanced.patches.music.video.playerresponse
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.music.utils.playservice.is_7_03_or_greater
import app.revanced.patches.music.utils.playservice.versionCheckPatch
import app.revanced.util.fingerprint.methodOrThrow
private const val REGISTER_VIDEO_ID = "p1"
private const val REGISTER_PLAYLIST_ID = "p4"
private const val REGISTER_PLAYLIST_INDEX = "p5"
private lateinit var playerResponseMethod: MutableMethod
val playerResponseMethodHookPatch = bytecodePatch(
description = "playerResponseMethodHookPatch"
) {
dependsOn(versionCheckPatch)
execute {
playerResponseMethod = if (is_7_03_or_greater) {
playerParameterBuilderFingerprint
} else {
playerParameterBuilderLegacyFingerprint
}.methodOrThrow()
}
}
fun hookPlayerResponse(
descriptor: String,
onlyVideoId: Boolean = false
) {
val smaliInstruction = if (onlyVideoId)
"invoke-static {$REGISTER_VIDEO_ID}, $descriptor"
else
"invoke-static {$REGISTER_VIDEO_ID, $REGISTER_PLAYLIST_ID, $REGISTER_PLAYLIST_INDEX}, $descriptor"
playerResponseMethod.addInstruction(0, smaliInstruction)
}

View File

@ -6,13 +6,11 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatchBuilder
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
import app.revanced.patches.shared.extension.Constants.SPOOF_PATH
import app.revanced.patches.shared.formatStreamModelConstructorFingerprint
import app.revanced.util.findInstructionIndicesReversedOrThrow
@ -381,13 +379,6 @@ fun baseSpoofStreamingDataPatch(
// endregion
findMethodOrThrow("$PATCHES_PATH/PatchStatus;") {
name == "SpoofStreamingData"
}.replaceInstruction(
0,
"const/4 v0, 0x1"
)
executeBlock()
}