feat(YouTube Music): Add support version 8.02.53

This commit is contained in:
inotia00 2025-01-17 14:58:44 +09:00
parent c8cc8c4bda
commit 4307b8e439
13 changed files with 110 additions and 73 deletions

View File

@ -49,9 +49,14 @@ val dislikeRedirectionPatch = bytecodePatch(
val onClickMethod = getWalkerMethod(onClickMethodIndex) val onClickMethod = getWalkerMethod(onClickMethodIndex)
onClickMethod.apply { onClickMethod.apply {
val onClickIndex = indexOfFirstInstructionOrThrow { val relativeIndex = indexOfFirstInstructionOrThrow {
val reference = opcode == Opcode.INVOKE_VIRTUAL &&
((this as? ReferenceInstruction)?.reference as? MethodReference) getReference<MethodReference>()
?.parameterTypes
?.contains("Ljava/util/Map;") == true
}
val onClickIndex = indexOfFirstInstructionOrThrow(relativeIndex) {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_INTERFACE && opcode == Opcode.INVOKE_INTERFACE &&
reference?.returnType == "V" && reference?.returnType == "V" &&

View File

@ -12,6 +12,8 @@ import app.revanced.patches.music.utils.settings.ResourceUtils.updatePatchStatus
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
import app.revanced.patches.music.utils.settings.settingsPatch import app.revanced.patches.music.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.indexOfFirstStringInstructionOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Suppress("unused") @Suppress("unused")
@ -25,9 +27,8 @@ val changeStartPagePatch = bytecodePatch(
execute { execute {
coldStartUpFingerprint.matchOrThrow().let { coldStartUpFingerprint.methodOrThrow().apply {
it.method.apply { val targetIndex = indexOfFirstStringInstructionOrThrow(DEFAULT_BROWSE_ID) + 1
val targetIndex = it.patternMatch!!.endIndex
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions( addInstructions(
@ -39,7 +40,6 @@ val changeStartPagePatch = bytecodePatch(
) )
removeInstruction(targetIndex) removeInstruction(targetIndex)
} }
}
addPreferenceWithIntent( addPreferenceWithIntent(
CategoryType.GENERAL, CategoryType.GENERAL,

View File

@ -5,16 +5,17 @@ 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.Opcode
const val DEFAULT_BROWSE_ID = "FEmusic_home"
internal val coldStartUpFingerprint = legacyFingerprint( internal val coldStartUpFingerprint = legacyFingerprint(
name = "coldStartUpFingerprint", name = "coldStartUpFingerprint",
returnType = "Ljava/lang/String;", returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
opcodes = listOf( opcodes = listOf(
Opcode.GOTO,
Opcode.CONST_STRING, Opcode.CONST_STRING,
Opcode.RETURN_OBJECT Opcode.RETURN_OBJECT
), ),
strings = listOf("FEmusic_library_sideloaded_tracks", "FEmusic_home") strings = listOf("FEmusic_library_sideloaded_tracks", DEFAULT_BROWSE_ID)
) )

View File

@ -22,7 +22,9 @@ internal val audioVideoSwitchToggleConstructorFingerprint = legacyFingerprint(
internal fun indexOfAudioVideoSwitchSetOnClickListenerInstruction(method: Method) = internal fun indexOfAudioVideoSwitchSetOnClickListenerInstruction(method: Method) =
method.indexOfFirstInstruction { method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL && opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.toString() == "Lcom/google/android/apps/youtube/music/player/AudioVideoSwitcherToggleView;->setOnClickListener(Landroid/view/View${'$'}OnClickListener;)V" getReference<MethodReference>()
?.toString()
?.endsWith("/AudioVideoSwitcherToggleView;->setOnClickListener(Landroid/view/View${'$'}OnClickListener;)V") == true
} }
internal val snackBarParentFingerprint = legacyFingerprint( internal val snackBarParentFingerprint = legacyFingerprint(

View File

@ -40,6 +40,7 @@ val cairoSplashAnimationPatch = bytecodePatch(
"7.06.54", "7.06.54",
"7.16.53", "7.16.53",
"7.25.53", "7.25.53",
"8.02.53",
), ),
) )

View File

@ -23,7 +23,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
const val AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY = const val AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY =
"Lcom/google/android/apps/youtube/music/player/AudioVideoSwitcherToggleView;->setVisibility(I)V" "/AudioVideoSwitcherToggleView;->setVisibility(I)V"
internal val audioVideoSwitchToggleFingerprint = legacyFingerprint( internal val audioVideoSwitchToggleFingerprint = legacyFingerprint(
name = "audioVideoSwitchToggleFingerprint", name = "audioVideoSwitchToggleFingerprint",
@ -33,7 +33,9 @@ internal val audioVideoSwitchToggleFingerprint = legacyFingerprint(
customFingerprint = { method, _ -> customFingerprint = { method, _ ->
method.indexOfFirstInstruction { method.indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL && opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.toString() == AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY getReference<MethodReference>()
?.toString()
?.endsWith(AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY) == true
} >= 0 } >= 0
} }
) )

View File

@ -799,7 +799,7 @@ val playerComponentsPatch = bytecodePatch(
val reference = (instruction as? ReferenceInstruction)?.reference val reference = (instruction as? ReferenceInstruction)?.reference
instruction.opcode == Opcode.INVOKE_VIRTUAL && instruction.opcode == Opcode.INVOKE_VIRTUAL &&
reference is MethodReference && reference is MethodReference &&
reference.toString() == AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY reference.toString().endsWith(AUDIO_VIDEO_SWITCH_TOGGLE_VISIBILITY)
} }
.map { (index, _) -> index } .map { (index, _) -> index }
.reversed() .reversed()
@ -995,7 +995,7 @@ val playerComponentsPatch = bytecodePatch(
val reference = getReference<MethodReference>() val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_INTERFACE && opcode == Opcode.INVOKE_INTERFACE &&
reference?.returnType == "Z" && reference?.returnType == "Z" &&
reference.parameterTypes.size == 0 reference.parameterTypes.isEmpty()
} + 1 } + 1
val targetRegister = val targetRegister =
getInstruction<OneRegisterInstruction>(targetIndex).registerA getInstruction<OneRegisterInstruction>(targetIndex).registerA

View File

@ -14,7 +14,8 @@ internal object Constants {
"6.42.55", // This is the latest version that supports Android 7.0 "6.42.55", // This is the latest version that supports Android 7.0
"6.51.53", // This is the latest version of YouTube Music 6.xx.xx "6.51.53", // This is the latest version of YouTube Music 6.xx.xx
"7.16.53", // This is the latest version that supports the 'Spoof app version' patch. "7.16.53", // This is the latest version that supports the 'Spoof app version' patch.
"7.25.53", // This is the latest version supported by the RVX patch. "7.25.53", // This is the last supported version for 2024.
"8.02.53", // This is the latest version supported by the RVX patch.
) )
) )
} }

View File

@ -1,26 +1,33 @@
package app.revanced.patches.music.utils.videotype package app.revanced.patches.music.utils.videotype
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.Opcode
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal val videoTypeFingerprint = legacyFingerprint( internal val videoTypeFingerprint = legacyFingerprint(
name = "videoTypeFingerprint", name = "videoTypeFingerprint",
returnType = "L", returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( customFingerprint = { method, _ ->
Opcode.IGET, indexOfGetEnumInstruction(method) >= 0
Opcode.INVOKE_STATIC, }
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.GOTO,
Opcode.SGET_OBJECT
)
) )
internal fun indexOfGetEnumInstruction(method: Method) =
method.indexOfFirstInstruction {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_STATIC &&
reference?.name == "a" &&
reference.parameterTypes.firstOrNull() == "I" &&
reference.definingClass == reference.returnType
}
internal val videoTypeParentFingerprint = legacyFingerprint( internal val videoTypeParentFingerprint = legacyFingerprint(
name = "videoTypeParentFingerprint", name = "videoTypeParentFingerprint",
returnType = "Z", returnType = "Z",

View File

@ -4,8 +4,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.music.utils.extension.Constants.UTILS_PATH import app.revanced.patches.music.utils.extension.Constants.UTILS_PATH
import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
private const val EXTENSION_CLASS_DESCRIPTOR = private const val EXTENSION_CLASS_DESCRIPTOR =
"$UTILS_PATH/VideoTypeHookPatch;" "$UTILS_PATH/VideoTypeHookPatch;"
@ -17,22 +23,27 @@ val videoTypeHookPatch = bytecodePatch(
execute { execute {
videoTypeFingerprint.matchOrThrow(videoTypeParentFingerprint).let { videoTypeFingerprint.methodOrThrow(videoTypeParentFingerprint).apply {
it.method.apply { val getEnumIndex = indexOfGetEnumInstruction(this)
val insertIndex = it.patternMatch!!.startIndex + 3 val enumClass = (getInstruction<ReferenceInstruction>(getEnumIndex).reference as MethodReference).definingClass
val referenceIndex = insertIndex + 1 val referenceIndex = indexOfFirstInstructionOrThrow(getEnumIndex) {
opcode == Opcode.SGET_OBJECT &&
getReference<FieldReference>()?.type == enumClass
}
val referenceInstruction = val referenceInstruction =
getInstruction<ReferenceInstruction>(referenceIndex).reference getInstruction<ReferenceInstruction>(referenceIndex).reference
val insertIndex = indexOfFirstInstructionOrThrow(getEnumIndex, Opcode.IF_NEZ)
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
addInstructionsWithLabels( addInstructionsWithLabels(
insertIndex, """ insertIndex, """
if-nez p0, :dismiss if-nez v$insertRegister, :dismiss
sget-object p0, $referenceInstruction sget-object v$insertRegister, $referenceInstruction
:dismiss :dismiss
invoke-static {p0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoType(Ljava/lang/Enum;)V invoke-static {v$insertRegister}, $EXTENSION_CLASS_DESCRIPTOR->setVideoType(Ljava/lang/Enum;)V
""" """
) )
} }
} }
} }
}

View File

@ -26,12 +26,6 @@ internal val videoIdFingerprint = legacyFingerprint(
returnType = "V", returnType = "V",
parameters = listOf("L", "Ljava/lang/String;"), parameters = listOf("L", "Ljava/lang/String;"),
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
opcodes = listOf(
Opcode.INVOKE_INTERFACE_RANGE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE_RANGE,
Opcode.MOVE_RESULT_OBJECT,
),
strings = listOf("Null initialPlayabilityStatus") strings = listOf("Null initialPlayabilityStatus")
) )

View File

@ -191,7 +191,12 @@ val videoInformationPatch = bytecodePatch(
*/ */
videoIdFingerprint.matchOrThrow().let { videoIdFingerprint.matchOrThrow().let {
it.method.apply { it.method.apply {
val playerResponseModelIndex = it.patternMatch!!.startIndex val playerResponseModelIndex = indexOfFirstInstructionOrThrow {
val reference = getReference<MethodReference>()
(opcode == Opcode.INVOKE_INTERFACE_RANGE || opcode == Opcode.INVOKE_INTERFACE) &&
reference?.returnType == "Ljava/lang/String;" &&
reference.parameterTypes.isEmpty()
}
PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR = PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR =
getInstruction(playerResponseModelIndex) getInstruction(playerResponseModelIndex)

View File

@ -2,9 +2,19 @@ package app.revanced.patches.music.video.playerresponse
import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or import app.revanced.util.or
import app.revanced.util.parametersEqual
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
private val PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST = listOf(
"Ljava/lang/String;", // VideoId.
"[B",
"Ljava/lang/String;", // Player parameters proto buffer.
"Ljava/lang/String;", // PlaylistId.
"I", // PlaylistIndex.
"I"
)
/** /**
* For targets 7.03 and later. * For targets 7.03 and later.
*/ */
@ -12,23 +22,21 @@ internal val playerParameterBuilderFingerprint = legacyFingerprint(
name = "playerParameterBuilderFingerprint", name = "playerParameterBuilderFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "L", returnType = "L",
parameters = listOf( strings = listOf("psps"),
"Ljava/lang/String;", // VideoId. customFingerprint = custom@{ method, _ ->
"[B", val parameterTypes = method.parameterTypes
"Ljava/lang/String;", // Player parameters proto buffer. val parameterSize = parameterTypes.size
"Ljava/lang/String;", // PlaylistId. if (parameterSize < 13) {
"I", // PlaylistIndex. return@custom false
"I", }
"L",
"Ljava/util/Set;", val startsWithMethodParameterList = parameterTypes.slice(0..5)
"Ljava/lang/String;",
"Ljava/lang/String;", parametersEqual(
"L", PLAYER_PARAMETER_STARTS_WITH_PARAMETER_LIST,
"Z", startsWithMethodParameterList
"Z", )
"Z", // Appears to indicate if the video id is being opened or is currently playing. }
),
strings = listOf("psps")
) )
/** /**