mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-08 18:44:34 +02:00
feat(YouTube Music): Add support version 8.02.53
This commit is contained in:
parent
c8cc8c4bda
commit
4307b8e439
@ -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" &&
|
||||||
|
@ -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,20 +27,18 @@ 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(
|
||||||
targetIndex + 1, """
|
targetIndex + 1, """
|
||||||
invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->changeStartPage(Ljava/lang/String;)Ljava/lang/String;
|
invoke-static {v$targetRegister}, $GENERAL_CLASS_DESCRIPTOR->changeStartPage(Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v$targetRegister
|
move-result-object v$targetRegister
|
||||||
return-object v$targetRegister
|
return-object v$targetRegister
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
removeInstruction(targetIndex)
|
removeInstruction(targetIndex)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addPreferenceWithIntent(
|
addPreferenceWithIntent(
|
||||||
|
@ -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)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -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",
|
||||||
|
@ -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) {
|
||||||
val referenceInstruction =
|
opcode == Opcode.SGET_OBJECT &&
|
||||||
getInstruction<ReferenceInstruction>(referenceIndex).reference
|
getReference<FieldReference>()?.type == enumClass
|
||||||
|
|
||||||
addInstructionsWithLabels(
|
|
||||||
insertIndex, """
|
|
||||||
if-nez p0, :dismiss
|
|
||||||
sget-object p0, $referenceInstruction
|
|
||||||
:dismiss
|
|
||||||
invoke-static {p0}, $EXTENSION_CLASS_DESCRIPTOR->setVideoType(Ljava/lang/Enum;)V
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
val referenceInstruction =
|
||||||
|
getInstruction<ReferenceInstruction>(referenceIndex).reference
|
||||||
|
|
||||||
|
val insertIndex = indexOfFirstInstructionOrThrow(getEnumIndex, Opcode.IF_NEZ)
|
||||||
|
val insertRegister = getInstruction<OneRegisterInstruction>(insertIndex).registerA
|
||||||
|
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
insertIndex, """
|
||||||
|
if-nez v$insertRegister, :dismiss
|
||||||
|
sget-object v$insertRegister, $referenceInstruction
|
||||||
|
:dismiss
|
||||||
|
invoke-static {v$insertRegister}, $EXTENSION_CLASS_DESCRIPTOR->setVideoType(Ljava/lang/Enum;)V
|
||||||
|
"""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user