mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-23 18:37:14 +02:00
feat(YouTube Music): add support versions 7.01.53
~ 7.02.51
This commit is contained in:
parent
904f1d6357
commit
f15a5d5259
@ -10,6 +10,7 @@ import app.revanced.patches.music.misc.minimizedplayback.fingerprints.MinimizedP
|
|||||||
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.MusicBrowserServiceFingerprint
|
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.MusicBrowserServiceFingerprint
|
||||||
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.PodCastConfigFingerprint
|
import app.revanced.patches.music.misc.minimizedplayback.fingerprints.PodCastConfigFingerprint
|
||||||
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||||
|
import app.revanced.util.getStartsWithStringInstructionIndex
|
||||||
import app.revanced.util.getStringInstructionIndex
|
import app.revanced.util.getStringInstructionIndex
|
||||||
import app.revanced.util.getWalkerMethod
|
import app.revanced.util.getWalkerMethod
|
||||||
import app.revanced.util.patch.BaseBytecodePatch
|
import app.revanced.util.patch.BaseBytecodePatch
|
||||||
@ -51,7 +52,7 @@ object MinimizedPlaybackPatch : BaseBytecodePatch(
|
|||||||
MusicBrowserServiceFingerprint.resultOrThrow().let {
|
MusicBrowserServiceFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val targetIndex =
|
val targetIndex =
|
||||||
getStringInstructionIndex("MBS: Return empty root for client: %s, isFullMediaBrowserEnabled: %b, is client browsable: %b, isRedAccount: %b")
|
getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s")
|
||||||
|
|
||||||
for (index in targetIndex downTo 0) {
|
for (index in targetIndex downTo 0) {
|
||||||
if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue
|
if (getInstruction(index).opcode != Opcode.INVOKE_VIRTUAL) continue
|
||||||
|
@ -2,14 +2,17 @@ package app.revanced.patches.music.misc.minimizedplayback.fingerprints
|
|||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import app.revanced.util.getStartsWithStringInstructionIndex
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal object MusicBrowserServiceFingerprint : MethodFingerprint(
|
internal object MusicBrowserServiceFingerprint : MethodFingerprint(
|
||||||
returnType = "L",
|
returnType = "L",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
parameters = listOf("Ljava/lang/String;", "Landroid/os/Bundle;"),
|
parameters = listOf("Ljava/lang/String;", "Landroid/os/Bundle;"),
|
||||||
strings = listOf("MBS: Return empty root for client: %s, isFullMediaBrowserEnabled: %b, is client browsable: %b, isRedAccount: %b"),
|
customFingerprint = custom@{ methodDef, _ ->
|
||||||
customFingerprint = { methodDef, _ ->
|
if (!methodDef.definingClass.endsWith("/MusicBrowserService;"))
|
||||||
methodDef.definingClass.endsWith("/MusicBrowserService;")
|
return@custom false
|
||||||
|
|
||||||
|
methodDef.getStartsWithStringInstructionIndex("MBS: Return empty root for client: %s") > 0
|
||||||
}
|
}
|
||||||
)
|
)
|
@ -10,8 +10,9 @@ object Constants {
|
|||||||
"6.29.58",
|
"6.29.58",
|
||||||
"6.31.55",
|
"6.31.55",
|
||||||
"6.33.52",
|
"6.33.52",
|
||||||
"6.50.53",
|
"6.51.53",
|
||||||
"6.51.53"
|
"7.01.53",
|
||||||
|
"7.02.51",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ import app.revanced.patches.music.utils.settings.fingerprints.GoogleApiActivityF
|
|||||||
import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerprint
|
import app.revanced.patches.music.utils.settings.fingerprints.PreferenceFingerprint
|
||||||
import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint
|
import app.revanced.patches.music.utils.settings.fingerprints.SettingsHeadersFragmentFingerprint
|
||||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_UTILS_CLASS_DESCRIPTOR
|
||||||
import app.revanced.patches.shared.settings.fingerprints.SharedSettingFingerprint
|
import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
@ -14,7 +14,7 @@ import app.revanced.patches.reddit.utils.resourceid.SharedResourceIdPatch.LabelA
|
|||||||
import app.revanced.patches.reddit.utils.settings.fingerprints.AcknowledgementsLabelBuilderFingerprint
|
import app.revanced.patches.reddit.utils.settings.fingerprints.AcknowledgementsLabelBuilderFingerprint
|
||||||
import app.revanced.patches.reddit.utils.settings.fingerprints.OssLicensesMenuActivityOnCreateFingerprint
|
import app.revanced.patches.reddit.utils.settings.fingerprints.OssLicensesMenuActivityOnCreateFingerprint
|
||||||
import app.revanced.patches.reddit.utils.settings.fingerprints.SettingsStatusLoadFingerprint
|
import app.revanced.patches.reddit.utils.settings.fingerprints.SettingsStatusLoadFingerprint
|
||||||
import app.revanced.patches.shared.settings.fingerprints.SharedSettingFingerprint
|
import app.revanced.patches.shared.fingerprints.SharedSettingFingerprint
|
||||||
import app.revanced.util.getTargetIndex
|
import app.revanced.util.getTargetIndex
|
||||||
import app.revanced.util.getWideLiteralInstructionIndex
|
import app.revanced.util.getWideLiteralInstructionIndex
|
||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package app.revanced.patches.shared.settings.fingerprints
|
package app.revanced.patches.shared.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_SETTING_CLASS_DESCRIPTOR
|
import app.revanced.patches.shared.integrations.Constants.INTEGRATIONS_SETTING_CLASS_DESCRIPTOR
|
@ -7,8 +7,10 @@ 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.extensions.InstructionExtensions.removeInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.smali.ExternalLabel
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.shared.integrations.Constants.COMPONENTS_PATH
|
import app.revanced.patches.shared.integrations.Constants.COMPONENTS_PATH
|
||||||
|
import app.revanced.patches.shared.litho.fingerprints.EmptyComponentsFingerprint
|
||||||
import app.revanced.patches.shared.litho.fingerprints.LithoFilterPatchConstructorFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.LithoFilterPatchConstructorFingerprint
|
||||||
import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.PathBuilderFingerprint
|
||||||
import app.revanced.patches.shared.litho.fingerprints.SetByteBufferFingerprint
|
import app.revanced.patches.shared.litho.fingerprints.SetByteBufferFingerprint
|
||||||
@ -19,6 +21,7 @@ import app.revanced.util.getTargetIndexWithFieldReferenceType
|
|||||||
import app.revanced.util.resultOrThrow
|
import app.revanced.util.resultOrThrow
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
|
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c
|
||||||
|
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.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
@ -26,8 +29,8 @@ import java.io.Closeable
|
|||||||
@Suppress("SpellCheckingInspection", "unused")
|
@Suppress("SpellCheckingInspection", "unused")
|
||||||
object LithoFilterPatch : BytecodePatch(
|
object LithoFilterPatch : BytecodePatch(
|
||||||
setOf(
|
setOf(
|
||||||
|
EmptyComponentsFingerprint,
|
||||||
LithoFilterPatchConstructorFingerprint,
|
LithoFilterPatchConstructorFingerprint,
|
||||||
PathBuilderFingerprint,
|
|
||||||
SetByteBufferFingerprint
|
SetByteBufferFingerprint
|
||||||
)
|
)
|
||||||
), Closeable {
|
), Closeable {
|
||||||
@ -40,6 +43,13 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
internal lateinit var addFilter: (String) -> Unit
|
internal lateinit var addFilter: (String) -> Unit
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private lateinit var emptyComponentMethod: MutableMethod
|
||||||
|
|
||||||
|
private lateinit var emptyComponentLabel: String
|
||||||
|
private lateinit var emptyComponentMethodName: String
|
||||||
|
|
||||||
|
private lateinit var pathBuilderMethodCall: String
|
||||||
|
|
||||||
private var filterCount = 0
|
private var filterCount = 0
|
||||||
|
|
||||||
override fun execute(context: BytecodeContext) {
|
override fun execute(context: BytecodeContext) {
|
||||||
@ -55,14 +65,75 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PathBuilderFingerprint.resultOrThrow().let {
|
EmptyComponentsFingerprint.resultOrThrow().let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
|
// resolves fingerprint.
|
||||||
|
PathBuilderFingerprint.resolve(context, it.classDef)
|
||||||
|
emptyComponentMethod = this
|
||||||
|
emptyComponentMethodName = name
|
||||||
|
|
||||||
val emptyComponentMethodIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
val emptyComponentMethodIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||||
val emptyComponentMethodReference =
|
val emptyComponentMethodReference =
|
||||||
getInstruction<ReferenceInstruction>(emptyComponentMethodIndex).reference
|
getInstruction<ReferenceInstruction>(emptyComponentMethodIndex).reference
|
||||||
val emptyComponentFieldReference =
|
val emptyComponentFieldReference =
|
||||||
getInstruction<ReferenceInstruction>(emptyComponentMethodIndex + 2).reference
|
getInstruction<ReferenceInstruction>(emptyComponentMethodIndex + 2).reference
|
||||||
|
|
||||||
|
emptyComponentLabel = """
|
||||||
|
move-object/from16 v0, p1
|
||||||
|
invoke-static {v0}, $emptyComponentMethodReference
|
||||||
|
move-result-object v0
|
||||||
|
iget-object v0, v0, $emptyComponentFieldReference
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PathBuilderFingerprint.resultOrThrow().let {
|
||||||
|
it.mutableMethod.apply {
|
||||||
|
// If the EmptyComponents Method and the PathBuilder Method are different,
|
||||||
|
// new inject way is required.
|
||||||
|
// TODO: Refactor LithoFilter patch when support for YouTube 18.29.38 ~ 19.17.41 and YT Music 6.29.58 ~ 6.51.53 is dropped.
|
||||||
|
if (emptyComponentMethodName != name) {
|
||||||
|
// In this case, the access modifier of the method that handles PathBuilder is 'AccessFlags.PRIVATE or AccessFlags.FINAL.
|
||||||
|
// Methods that handle PathBuilder are invoked by methods that handle EmptyComponents.
|
||||||
|
// 'pathBuilderMethodCall' is a reference that invokes the PathBuilder Method.
|
||||||
|
pathBuilderMethodCall = "$definingClass->$name("
|
||||||
|
for (i in 0 until parameters.size) {
|
||||||
|
pathBuilderMethodCall += parameterTypes[i]
|
||||||
|
}
|
||||||
|
pathBuilderMethodCall += ")$returnType"
|
||||||
|
|
||||||
|
emptyComponentMethod.apply {
|
||||||
|
// If the return value of the PathBuilder Method is null,
|
||||||
|
// it means that pathBuilder has been filtered by the LithoFilterPatch.
|
||||||
|
// (Refer comments below.)
|
||||||
|
// Returns emptyComponents.
|
||||||
|
for (index in implementation!!.instructions.size - 1 downTo 0) {
|
||||||
|
val instruction = getInstruction(index)
|
||||||
|
if ((instruction as? ReferenceInstruction)?.reference.toString() != pathBuilderMethodCall)
|
||||||
|
continue
|
||||||
|
|
||||||
|
val insertRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||||
|
val insertIndex = index + 2
|
||||||
|
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
insertIndex, """
|
||||||
|
if-nez v$insertRegister, :ignore
|
||||||
|
""" + emptyComponentLabel,
|
||||||
|
ExternalLabel("ignore", getInstruction(insertIndex))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the EmptyComponents Method and the PathBuilder Method are different,
|
||||||
|
// PathBuilder Method's returnType cannot cast emptyComponents.
|
||||||
|
// So just returns null value.
|
||||||
|
emptyComponentLabel = """
|
||||||
|
const/4 v0, 0x0
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
val stringBuilderIndex = getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;")
|
val stringBuilderIndex = getTargetIndexWithFieldReferenceType("Ljava/lang/StringBuilder;")
|
||||||
val stringBuilderRegister = getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
val stringBuilderRegister = getInstruction<TwoRegisterInstruction>(stringBuilderIndex).registerA
|
||||||
|
|
||||||
@ -81,12 +152,8 @@ object LithoFilterPatch : BytecodePatch(
|
|||||||
invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister}, $INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;)Z
|
invoke-static {v$stringBuilderRegister, v$identifierRegister, v$objectRegister}, $INTEGRATIONS_LITHO_FILER_CLASS_DESCRIPTOR->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/lang/Object;)Z
|
||||||
move-result v$stringBuilderRegister
|
move-result v$stringBuilderRegister
|
||||||
if-eqz v$stringBuilderRegister, :filter
|
if-eqz v$stringBuilderRegister, :filter
|
||||||
move-object/from16 v0, p1
|
""" + emptyComponentLabel,
|
||||||
invoke-static {v0}, $emptyComponentMethodReference
|
ExternalLabel("filter", getInstruction(insertIndex))
|
||||||
move-result-object v0
|
|
||||||
iget-object v0, v0, $emptyComponentFieldReference
|
|
||||||
return-object v0
|
|
||||||
""", ExternalLabel("filter", getInstruction(insertIndex))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package app.revanced.patches.shared.litho.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
|
internal object EmptyComponentsFingerprint : MethodFingerprint(
|
||||||
|
returnType = "L",
|
||||||
|
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.INVOKE_STATIC_RANGE,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.IGET_OBJECT
|
||||||
|
),
|
||||||
|
strings = listOf("Error while converting %s")
|
||||||
|
)
|
@ -1,18 +1,11 @@
|
|||||||
package app.revanced.patches.shared.litho.fingerprints
|
package app.revanced.patches.shared.litho.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since YouTube v19.18.41 and YT Music 7.01.53, pathBuilder is being handled by a different Method.
|
||||||
|
*/
|
||||||
internal object PathBuilderFingerprint : MethodFingerprint(
|
internal object PathBuilderFingerprint : MethodFingerprint(
|
||||||
returnType = "L",
|
returnType = "L",
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
strings = listOf("Number of bits must be positive")
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_INTERFACE,
|
|
||||||
Opcode.INVOKE_STATIC_RANGE,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.IGET_OBJECT
|
|
||||||
),
|
|
||||||
strings = listOf("Error while converting %s")
|
|
||||||
)
|
)
|
@ -18,7 +18,6 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMut
|
|||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
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.builder.instruction.BuilderInstruction21c
|
|
||||||
import com.android.tools.smali.dexlib2.iface.Method
|
import com.android.tools.smali.dexlib2.iface.Method
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
@ -212,7 +211,14 @@ fun Method.getEmptyStringInstructionIndex()
|
|||||||
fun Method.getStringInstructionIndex(value: String) = implementation?.let {
|
fun Method.getStringInstructionIndex(value: String) = implementation?.let {
|
||||||
it.instructions.indexOfFirst { instruction ->
|
it.instructions.indexOfFirst { instruction ->
|
||||||
instruction.opcode == Opcode.CONST_STRING
|
instruction.opcode == Opcode.CONST_STRING
|
||||||
&& (instruction as? BuilderInstruction21c)?.reference.toString() == value
|
&& (instruction as? ReferenceInstruction)?.reference.toString() == value
|
||||||
|
}
|
||||||
|
} ?: -1
|
||||||
|
|
||||||
|
fun Method.getStartsWithStringInstructionIndex(value: String) = implementation?.let {
|
||||||
|
it.instructions.indexOfFirst { instruction ->
|
||||||
|
instruction.opcode == Opcode.CONST_STRING
|
||||||
|
&& (instruction as? ReferenceInstruction)?.reference.toString().startsWith(value)
|
||||||
}
|
}
|
||||||
} ?: -1
|
} ?: -1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user