feat: Patches for YouTube Music

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX 2022-04-26 23:10:36 +02:00
parent 62f1801e9c
commit b60c9d33b6
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
14 changed files with 383 additions and 24 deletions

View File

@ -1,16 +1,15 @@
package app.revanced.patches package app.revanced.patches
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patches.ad.HomeAdsPatch import app.revanced.patches.music.audio.EnableAudioOnlyPatch
import app.revanced.patches.ad.HomePromoPatch import app.revanced.patches.music.layout.RemoveUpgradeTabPatch
import app.revanced.patches.ad.VideoAdsPatch import app.revanced.patches.music.premium.BackgroundPlayPatch
import app.revanced.patches.interaction.EnableSeekbarTappingPatch import app.revanced.patches.youtube.ad.HomeAdsPatch
import app.revanced.patches.layout.CreateButtonRemoverPatch import app.revanced.patches.youtube.ad.HomePromoPatch
import app.revanced.patches.layout.ShortsButtonRemoverPatch import app.revanced.patches.youtube.ad.VideoAdsPatch
import app.revanced.patches.layout.HideReelsPatch import app.revanced.patches.youtube.interaction.EnableSeekbarTappingPatch
import app.revanced.patches.layout.MinimizedPlaybackPatch import app.revanced.patches.youtube.layout.*
import app.revanced.patches.layout.OldQualityLayoutPatch import app.revanced.patches.youtube.misc.IntegrationsPatch
import app.revanced.patches.misc.IntegrationsPatch
/** /**
* Index contains all the patches. * Index contains all the patches.
@ -31,6 +30,9 @@ object Index {
::ShortsButtonRemoverPatch, ::ShortsButtonRemoverPatch,
::HideReelsPatch, ::HideReelsPatch,
::OldQualityLayoutPatch, ::OldQualityLayoutPatch,
::EnableSeekbarTappingPatch ::EnableSeekbarTappingPatch,
::EnableAudioOnlyPatch,
::RemoveUpgradeTabPatch,
::BackgroundPlayPatch
) )
} }

View File

@ -0,0 +1,128 @@
package app.revanced.patches.music.audio
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("05.03.50")
)
)
class EnableAudioOnlyPatch : Patch(
PatchMetadata(
"audio-only-playback-patch",
"Audio Only Mode Patch",
"Add the option to play music without video.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"audio-only-method-signature",
MethodMetadata("Lgmd;", "c"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.NOP,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.RETURN_VOID
)
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
val result = signatures.first().result!!.findParentMethod(
MethodSignature(
MethodSignatureMetadata(
"audio-only-enabler-method",
MethodMetadata("Lgmd;", "d"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"Z",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.GOTO,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.RETURN
)
)
) ?: return PatchResultError("Required method for ${metadata.shortName} not found.")
val implementation = result.method.implementation!!
implementation.replaceInstruction(
implementation.instructions.count() - 1,
"const/4 v0, 0x1".toInstruction()
)
implementation.addInstruction(
"return v0".toInstruction()
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,144 @@
package app.revanced.patches.music.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction22t
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("05.03.50")
)
)
class RemoveUpgradeTabPatch : Patch(
PatchMetadata(
"upgrade-tab-remover",
"Remove Upgrade Tab Patch",
"Remove the upgrade tab from t he pivot bar in YouTube music.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"pivot-bar-constructor",
MethodMetadata("Lhfu;", "<init2>"), // unknown
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Required signature for this patch.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.NOP,
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID
)
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
val result = signatures.first().result!!
val implementation = result.method.implementation!!
val pivotBarElementFieldRef =
(implementation.instructions[result.scanData.endIndex - 1] as Instruction22c).reference
// first compile all the needed instructions
val instructionList =
"""
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x3
const/4 v1, 0x3
invoke-interface {v0, v1}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, p0, $pivotBarElementFieldRef
""".trimIndent().toInstructions().toMutableList()
// replace the instruction to retain the label at given index
implementation.replaceInstruction(
result.scanData.endIndex - 1,
instructionList[0] // invoke-interface
)
val exitInstruction = instructionList.last() // iput-object
implementation.addInstruction(
result.scanData.endIndex,
exitInstruction
)
// do not forget to remove this instruction since we added it already
instructionList.removeLast()
// add the necessary if statement to remove the upgrade tab button in case it exists
instructionList.add(
3, // if-le
BuilderInstruction22t(
Opcode.IF_LE,
1, 2,
implementation.newLabelForIndex(result.scanData.endIndex)
)
)
implementation.addInstructions(
result.scanData.endIndex,
instructionList
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,88 @@
package app.revanced.patches.music.premium
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("05.03.50")
)
)
class BackgroundPlayPatch : Patch(
PatchMetadata(
"background-play",
"Enable Background Playback Patch",
"Enable playing music in the background.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"background-playback-disabler-method",
MethodMetadata("Lafgf;", "e"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),
listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN,
Opcode.RETURN
)
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
signatures.first().result!!.method.implementation!!.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""".trimIndent().toInstructions()
)
return PatchResultSuccess()
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.ad package app.revanced.patches.youtube.ad
import app.revanced.extensions.injectHideCall import app.revanced.extensions.injectHideCall
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData

View File

@ -1,4 +1,4 @@
package app.revanced.patches.ad package app.revanced.patches.youtube.ad
import app.revanced.extensions.injectHideCall import app.revanced.extensions.injectHideCall
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData

View File

@ -1,4 +1,4 @@
package app.revanced.patches.ad package app.revanced.patches.youtube.ad
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.interaction package app.revanced.patches.youtube.interaction
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.layout package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or

View File

@ -1,4 +1,4 @@
package app.revanced.patches.layout package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or

View File

@ -1,4 +1,4 @@
package app.revanced.patches.layout package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.layout package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions

View File

@ -1,4 +1,4 @@
package app.revanced.patches.layout package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
@ -10,10 +10,7 @@ import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction import app.revanced.patcher.smali.toInstruction
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.instruction.formats.Instruction3rc
import org.jf.dexlib2.iface.instruction.formats.Instruction11x import org.jf.dexlib2.iface.instruction.formats.Instruction11x
import org.jf.dexlib2.builder.instruction.BuilderInstruction32x
private val compatiblePackages = listOf( private val compatiblePackages = listOf(
PackageMetadata( PackageMetadata(

View File

@ -1,4 +1,4 @@
package app.revanced.patches.misc package app.revanced.patches.youtube.misc
import app.revanced.patcher.PatcherData import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions