feat(YouTube Music): Add support version 8.05.50, Remove support version 8.02.53 https://github.com/inotia00/ReVanced_Extended/issues/2769

This commit is contained in:
inotia00 2025-02-07 18:00:32 +09:00
parent 38949e12fd
commit c575ffc45b
7 changed files with 118 additions and 35 deletions

View File

@ -306,23 +306,32 @@ internal val repeatTrackFingerprint = legacyFingerprint(
strings = listOf("w_st") strings = listOf("w_st")
) )
internal const val SHUFFLE_BUTTON_ID = 45468L
internal val shuffleOnClickFingerprint = legacyFingerprint( internal val shuffleOnClickFingerprint = legacyFingerprint(
name = "shuffleOnClickFingerprint", name = "shuffleOnClickFingerprint",
returnType = "V", returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf("Landroid/view/View;"), parameters = listOf("Landroid/view/View;"),
literals = listOf(45468L), literals = listOf(SHUFFLE_BUTTON_ID),
customFingerprint = { method, _ -> customFingerprint = { method, _ ->
method.name == "onClick" && method.name == "onClick"
indexOfAccessibilityInstruction(method) >= 0
} }
) )
internal fun indexOfAccessibilityInstruction(method: Method) = internal val shuffleEnumFingerprint = legacyFingerprint(
method.indexOfFirstInstruction { name = "shuffleEnumFingerprint",
opcode == Opcode.INVOKE_VIRTUAL && returnType = "V",
getReference<MethodReference>()?.name == "announceForAccessibility" parameters = emptyList(),
strings = listOf(
"SHUFFLE_OFF",
"SHUFFLE_ALL",
"SHUFFLE_DISABLED",
),
customFingerprint = { method, _ ->
method.name == "<clinit>"
} }
)
internal val swipeToCloseFingerprint = legacyFingerprint( internal val swipeToCloseFingerprint = legacyFingerprint(
name = "swipeToCloseFingerprint", name = "swipeToCloseFingerprint",

View File

@ -24,6 +24,7 @@ import app.revanced.patches.music.utils.playservice.is_6_27_or_greater
import app.revanced.patches.music.utils.playservice.is_6_42_or_greater import app.revanced.patches.music.utils.playservice.is_6_42_or_greater
import app.revanced.patches.music.utils.playservice.is_7_18_or_greater import app.revanced.patches.music.utils.playservice.is_7_18_or_greater
import app.revanced.patches.music.utils.playservice.is_7_25_or_greater import app.revanced.patches.music.utils.playservice.is_7_25_or_greater
import app.revanced.patches.music.utils.playservice.is_8_03_or_greater
import app.revanced.patches.music.utils.playservice.versionCheckPatch import app.revanced.patches.music.utils.playservice.versionCheckPatch
import app.revanced.patches.music.utils.resourceid.colorGrey import app.revanced.patches.music.utils.resourceid.colorGrey
import app.revanced.patches.music.utils.resourceid.darkBackground import app.revanced.patches.music.utils.resourceid.darkBackground
@ -57,6 +58,7 @@ import app.revanced.util.fingerprint.mutableClassOrThrow
import app.revanced.util.fingerprint.resolvable import app.revanced.util.fingerprint.resolvable
import app.revanced.util.getReference import app.revanced.util.getReference
import app.revanced.util.getWalkerMethod import app.revanced.util.getWalkerMethod
import app.revanced.util.indexOfFirstInstruction
import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
@ -65,6 +67,7 @@ import app.revanced.util.insertNode
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.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
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 import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
@ -72,6 +75,7 @@ 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.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.immutable.ImmutableField import com.android.tools.smali.dexlib2.immutable.ImmutableField
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
import org.w3c.dom.Element import org.w3c.dom.Element
private const val IMAGE_VIEW_TAG_NAME = private const val IMAGE_VIEW_TAG_NAME =
@ -850,17 +854,28 @@ val playerComponentsPatch = bytecodePatch(
// region patch for remember shuffle state // region patch for remember shuffle state
shuffleOnClickFingerprint.methodOrThrow().apply { shuffleOnClickFingerprint.methodOrThrow().apply {
val accessibilityIndex = indexOfAccessibilityInstruction(this)
// region set shuffle enum // region set shuffle enum
val enumClass = shuffleEnumFingerprint.methodOrThrow().definingClass
val enumIndex = indexOfFirstInstructionReversedOrThrow(accessibilityIndex) { val startIndex = indexOfFirstLiteralInstructionOrThrow(SHUFFLE_BUTTON_ID)
val (enumIndex, enumRegister) = if (is_8_03_or_greater) {
val index = indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.returnType == enumClass
}
val register = getInstruction<OneRegisterInstruction>(index + 1).registerA
Pair(index + 2, register)
} else {
val index = indexOfFirstInstructionReversedOrThrow(startIndex) {
opcode == Opcode.INVOKE_DIRECT && opcode == Opcode.INVOKE_DIRECT &&
getReference<MethodReference>()?.returnType == "Ljava/lang/String;" getReference<MethodReference>()?.returnType == "Ljava/lang/String;"
} }
val enumRegister = getInstruction<FiveRegisterInstruction>(enumIndex).registerD val register = getInstruction<FiveRegisterInstruction>(index).registerD
val enumClass =
(getInstruction<ReferenceInstruction>(enumIndex).reference as MethodReference).parameterTypes.first() Pair(index, register)
}
addInstruction( addInstruction(
enumIndex, enumIndex,
@ -872,7 +887,7 @@ val playerComponentsPatch = bytecodePatch(
// region set static field // region set static field
val shuffleClassIndex = val shuffleClassIndex =
indexOfFirstInstructionReversedOrThrow(accessibilityIndex, Opcode.CHECK_CAST) indexOfFirstInstructionReversedOrThrow(enumIndex, Opcode.CHECK_CAST)
val shuffleClass = val shuffleClass =
getInstruction<ReferenceInstruction>(shuffleClassIndex).reference.toString() getInstruction<ReferenceInstruction>(shuffleClassIndex).reference.toString()
val shuffleMutableClass = classBy { classDef -> val shuffleMutableClass = classBy { classDef ->
@ -901,18 +916,56 @@ val playerComponentsPatch = bytecodePatch(
// region make all methods accessible // region make all methods accessible
fun Method.indexOfEnumOrdinalInstruction() =
indexOfFirstInstruction {
val reference = getReference<MethodReference>()
opcode == Opcode.INVOKE_VIRTUAL &&
reference?.name == "ordinal" &&
reference.definingClass == enumClass
}
val isShuffleMethod: Method.() -> Boolean = {
returnType == "V" &&
indexOfEnumOrdinalInstruction() >= 0 &&
indexOfFirstInstruction {
opcode == Opcode.INVOKE_VIRTUAL &&
getReference<MethodReference>()?.name == "post"
} >= 0
}
val shuffleMethod = shuffleMutableClass.methods.find { method -> val shuffleMethod = shuffleMutableClass.methods.find { method ->
method.parameterTypes.firstOrNull() == enumClass && method.isShuffleMethod()
method.parameterTypes.size == 1 &&
method.returnType == "V"
} ?: throw PatchException("shuffle method not found") } ?: throw PatchException("shuffle method not found")
val shuffleMethodRegisterCount = shuffleMethod.implementation!!.registerCount
shuffleMutableClass.methods.add( shuffleMutableClass.methods.add(
shuffleMethod.cloneMutable( shuffleMethod.cloneMutable(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
name = "shuffleTracks" name = "shuffleTracks",
registerCount = if (is_8_03_or_greater) {
shuffleMethodRegisterCount + 1
} else {
shuffleMethodRegisterCount
},
parameters = listOf(
ImmutableMethodParameter(
enumClass,
annotations,
"enumClass"
) )
) )
).apply {
if (is_8_03_or_greater) {
val index = indexOfEnumOrdinalInstruction()
val register = getInstruction<FiveRegisterInstruction>(index).registerC
addInstruction(
index,
"move-object/from16 v$register, p1"
)
}
}
)
// endregion // endregion

View File

@ -15,7 +15,7 @@ internal object Constants {
"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 last supported version for 2024. "7.25.53", // This is the last supported version for 2024.
"8.02.53", // This is the latest version supported by the RVX patch. "8.05.50", // This is the latest version supported by the RVX patch.
) )
) )
} }

View File

@ -33,6 +33,8 @@ var is_7_27_or_greater = false
private set private set
var is_7_29_or_greater = false var is_7_29_or_greater = false
private set private set
var is_8_03_or_greater = false
private set
val versionCheckPatch = resourcePatch( val versionCheckPatch = resourcePatch(
description = "versionCheckPatch", description = "versionCheckPatch",
@ -62,5 +64,6 @@ val versionCheckPatch = resourcePatch(
is_7_25_or_greater = 244399000 <= playStoreServicesVersion is_7_25_or_greater = 244399000 <= playStoreServicesVersion
is_7_27_or_greater = 244515000 <= playStoreServicesVersion is_7_27_or_greater = 244515000 <= playStoreServicesVersion
is_7_29_or_greater = 244799000 <= playStoreServicesVersion is_7_29_or_greater = 244799000 <= playStoreServicesVersion
is_8_03_or_greater = 250399000 <= playStoreServicesVersion
} }
} }

View File

@ -10,6 +10,7 @@ import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.reference.FieldReference import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
internal val createPlayerRequestBodyWithModelFingerprint = legacyFingerprint( internal val createPlayerRequestBodyWithModelFingerprint = legacyFingerprint(
name = "createPlayerRequestBodyWithModelFingerprint", name = "createPlayerRequestBodyWithModelFingerprint",
@ -75,8 +76,13 @@ internal val sharedSettingFingerprint = legacyFingerprint(
internal val spannableStringBuilderFingerprint = legacyFingerprint( internal val spannableStringBuilderFingerprint = legacyFingerprint(
name = "spannableStringBuilderFingerprint", name = "spannableStringBuilderFingerprint",
returnType = "Ljava/lang/CharSequence;", returnType = "Ljava/lang/CharSequence;",
strings = listOf("Failed to set PB Style Run Extension in TextComponentSpec. Extension id: %s"),
customFingerprint = { method, _ -> customFingerprint = { method, _ ->
method.indexOfFirstInstruction {
opcode == Opcode.CONST_STRING &&
getReference<StringReference>()
?.string.toString()
.startsWith("Failed to set PB Style Run Extension in TextComponentSpec.")
} >= 0 &&
indexOfSpannableStringInstruction(method) >= 0 indexOfSpannableStringInstruction(method) >= 0
} }
) )

View File

@ -1,16 +1,21 @@
package app.revanced.patches.shared.litho package app.revanced.patches.shared.litho
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.reference.StringReference
internal const val BUFFER_UPD_FEATURE_FLAG = 45419603L
internal val bufferUpbFeatureFlagFingerprint = legacyFingerprint( internal val bufferUpbFeatureFlagFingerprint = legacyFingerprint(
name = "bufferUpbFeatureFlagFingerprint", name = "bufferUpbFeatureFlagFingerprint",
returnType = "L", returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
literals = listOf(45419603L), literals = listOf(BUFFER_UPD_FEATURE_FLAG),
) )
internal val byteBufferFingerprint = legacyFingerprint( internal val byteBufferFingerprint = legacyFingerprint(
@ -51,9 +56,16 @@ internal val emptyComponentsFingerprint = legacyFingerprint(
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_STATIC_RANGE, Opcode.INVOKE_STATIC_RANGE,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT Opcode.IGET_OBJECT,
), ),
strings = listOf("Error while converting %s"), customFingerprint = { method, _ ->
method.indexOfFirstInstruction {
opcode == Opcode.CONST_STRING &&
getReference<StringReference>()
?.string.toString()
.startsWith("Error while converting")
} >= 0
}
) )
/** /**
@ -65,10 +77,12 @@ internal val pathBuilderFingerprint = legacyFingerprint(
strings = listOf("Number of bits must be positive"), strings = listOf("Number of bits must be positive"),
) )
internal const val PATH_UPD_FEATURE_FLAG = 45631264L
internal val pathUpbFeatureFlagFingerprint = legacyFingerprint( internal val pathUpbFeatureFlagFingerprint = legacyFingerprint(
name = "pathUpbFeatureFlagFingerprint", name = "pathUpbFeatureFlagFingerprint",
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(), parameters = emptyList(),
literals = listOf(45631264L), literals = listOf(PATH_UPD_FEATURE_FLAG),
) )

View File

@ -165,13 +165,11 @@ val lithoFilterPatch = bytecodePatch(
// Turn off native code that handles litho component names. If this feature is on then nearly // Turn off native code that handles litho component names. If this feature is on then nearly
// all litho components have a null name and identifier/path filtering is completely broken. // all litho components have a null name and identifier/path filtering is completely broken.
if (bufferUpbFeatureFlagFingerprint.second.methodOrNull != null &&
pathUpbFeatureFlagFingerprint.second.methodOrNull != null
) {
mapOf( mapOf(
bufferUpbFeatureFlagFingerprint to 45419603L, bufferUpbFeatureFlagFingerprint to BUFFER_UPD_FEATURE_FLAG,
pathUpbFeatureFlagFingerprint to 45631264L, pathUpbFeatureFlagFingerprint to PATH_UPD_FEATURE_FLAG,
).forEach { (fingerprint, literalValue) -> ).forEach { (fingerprint, literalValue) ->
if (fingerprint.second.methodOrNull != null) {
fingerprint.injectLiteralInstructionBooleanCall( fingerprint.injectLiteralInstructionBooleanCall(
literalValue, literalValue,
"0x0" "0x0"