diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 521de809..274be198 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -302,6 +302,12 @@ public final class app/revanced/patches/moneymanager/UnlockProPatch : app/revanc public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/ad/video/HideMusicVideoAds : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/ad/video/HideMusicVideoAds; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/ad/video/MusicVideoAdsPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/ad/video/MusicVideoAdsPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -314,6 +320,12 @@ public final class app/revanced/patches/music/audio/codecs/CodecsUnlockPatch : a public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -326,6 +338,12 @@ public final class app/revanced/patches/music/interaction/permanentrepeat/Perman public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/interaction/permanentshuffle/PermanentShuffleTogglePatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V @@ -338,6 +356,12 @@ public final class app/revanced/patches/music/layout/compactheader/CompactHeader public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/music/layout/compactheader/HideCategoryBar : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/music/layout/compactheader/HideCategoryBar; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt new file mode 100644 index 00000000..6f533c2f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/ad/video/HideMusicVideoAds.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.music.ad.video + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsParentFingerprint +import app.revanced.util.exception + +@Patch( + name = "Hide music video ads", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], +) +@Suppress("unused") +object HideMusicVideoAds : BytecodePatch( + setOf(ShowMusicVideoAdsParentFingerprint), +) { + override fun execute(context: BytecodeContext) { + ShowMusicVideoAdsParentFingerprint.result?.let { + val showMusicVideoAdsMethod = context + .toMethodWalker(it.mutableMethod) + .nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod + + showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0") + } ?: throw ShowMusicVideoAdsParentFingerprint.exception + } +} + +@Deprecated("This patch class has been renamed to HideMusicVideoAds.") +object MusicVideoAdsPatch : BytecodePatch( + dependencies = setOf(HideMusicVideoAds::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt deleted file mode 100644 index e2f1978e..00000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/MusicVideoAdsPatch.kt +++ /dev/null @@ -1,32 +0,0 @@ -package app.revanced.patches.music.ad.video - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint - -@Patch( - name = "Music video ads", - description = "Removes ads in the music player.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] -) -@Suppress("unused") -object MusicVideoAdsPatch : BytecodePatch( - setOf(ShowMusicVideoAdsConstructorFingerprint) -) { - override fun execute(context: BytecodeContext) { - ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef) - - val result = ShowMusicVideoAdsFingerprint.result!! - - result.mutableMethod.addInstruction( - result.scanResult.patternScanResult!!.startIndex, - """ - const/4 p1, 0x0 - """ - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt deleted file mode 100644 index 1a1b9be8..00000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt +++ /dev/null @@ -1,27 +0,0 @@ -package app.revanced.patches.music.ad.video.fingerprints -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -internal object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.IPUT_BOOLEAN, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt deleted file mode 100644 index 952b866d..00000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.music.ad.video.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 ShowMusicVideoAdsFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf( - Opcode.IPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt new file mode 100644 index 00000000..5996ee98 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsParentFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.music.ad.video.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint( + opcodes = listOf( + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + ), + strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."), +) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt index 35fa977a..0c1cbebc 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/CodecsUnlockPatch.kt @@ -10,13 +10,12 @@ import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprin import com.android.tools.smali.dexlib2.Opcode @Patch( - name = "Codecs unlock", description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) -@Suppress("unused") +@Deprecated("This patch is no longer needed as the feature is now enabled by default.") object CodecsUnlockPatch : BytecodePatch( - setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint) + setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint), ) { override fun execute(context: BytecodeContext) { val codecsLockResult = CodecsLockFingerprint.result!! @@ -25,13 +24,13 @@ object CodecsUnlockPatch : BytecodePatch( val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex val instructionIndex = scanResultStartIndex + - if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) { - // for 5.16.xx and lower - -3 - } else { - // since 5.17.xx - -2 - } + if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) { + // for 5.16.xx and lower + -3 + } else { + // since 5.17.xx + -2 + } val allCodecsResult = AllCodecsReferenceFingerprint.result!! val allCodecsMethod = @@ -41,7 +40,7 @@ object CodecsUnlockPatch : BytecodePatch( implementation.replaceInstruction( instructionIndex, - "invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction() + "invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction(), ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt similarity index 68% rename from src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt rename to src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt index 8955c77c..79f3fc0f 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/ExclusiveAudioPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/EnableExclusiveAudioPlayback.kt @@ -1,31 +1,36 @@ package app.revanced.patches.music.audio.exclusiveaudio -import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AllowExclusiveAudioPlaybackFingerprint +import app.revanced.util.exception @Patch( - name = "Exclusive audio playback", + name = "Enable exclusive audio playback", description = "Enables the option to play audio without video.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object ExclusiveAudioPatch : BytecodePatch( - setOf(AllowExclusiveAudioPlaybackFingerprint) +object EnableExclusiveAudioPlayback : BytecodePatch( + setOf(AllowExclusiveAudioPlaybackFingerprint), ) { override fun execute(context: BytecodeContext) { AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply { addInstructions( 0, - """ + """ const/4 v0, 0x1 return v0 - """ + """, ) } ?: throw AllowExclusiveAudioPlaybackFingerprint.exception } -} \ No newline at end of file +} + +@Deprecated("This patch class has been renamed to EnableExclusiveAudioPlayback.") +object ExclusiveAudioPatch : BytecodePatch(emptySet()) { + override fun execute(context: BytecodeContext) = EnableExclusiveAudioPlayback.execute(context) +} diff --git a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt index 70eb16a6..88dff320 100644 --- a/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/interaction/permanentshuffle/PermanentShufflePatch.kt @@ -1,25 +1,32 @@ package app.revanced.patches.music.interaction.permanentshuffle -import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint - +import app.revanced.util.exception @Patch( name = "Permanent shuffle", description = "Permanently remember your shuffle preference " + - "even if the playlist ends or another track is played.", + "even if the playlist ends or another track is played.", compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], - use = false + use = false, ) @Suppress("unused") -object PermanentShuffleTogglePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) { +object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) { override fun execute(context: BytecodeContext) { DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void") ?: throw DisableShuffleFingerprint.exception } } + +@Deprecated("This patch class has been renamed to PermanentShufflePatch.") +object PermanentShuffleTogglePatch : BytecodePatch( + dependencies = setOf(PermanentShufflePatch::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt deleted file mode 100644 index ec67f2d6..00000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/CompactHeaderPatch.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.patches.music.layout.compactheader - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction11x - -@Patch( - name = "Compact header", - description = "Hides the music category bar at the top of the homepage.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], - use = false -) -@Suppress("unused") -object CompactHeaderPatch : BytecodePatch( - setOf(CompactHeaderConstructorFingerprint) -) { - override fun execute(context: BytecodeContext) { - val result = CompactHeaderConstructorFingerprint.result!! - val method = result.mutableMethod - - val insertIndex = result.scanResult.patternScanResult!!.endIndex - val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA - method.addInstructions( - insertIndex, """ - const/16 v2, 0x8 - invoke-virtual {v${register}, v2}, Landroid/view/View;->setVisibility(I)V - """ - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt new file mode 100644 index 00000000..0cc8e949 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/HideCategoryBar.kt @@ -0,0 +1,47 @@ +package app.revanced.patches.music.layout.compactheader + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.music.layout.compactheader.fingerprints.ConstructCategoryBarFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Hide category bar", + description = "Hides the category bar at the top of the homepage.", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], + use = false, +) +@Suppress("unused") +object HideCategoryBar : BytecodePatch( + setOf(ConstructCategoryBarFingerprint), +) { + override fun execute(context: BytecodeContext) { + ConstructCategoryBarFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.startIndex + val register = getInstruction(insertIndex - 1).registerA + + addInstructions( + insertIndex, + """ + const/16 v2, 0x8 + invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V + """, + ) + } + } ?: throw ConstructCategoryBarFingerprint.exception + } +} + +@Deprecated("This patch class has been renamed to HideCategoryBar.") +object CompactHeaderPatch : BytecodePatch( + dependencies = setOf(HideCategoryBar::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt similarity index 56% rename from src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt index 98587cc9..903222c5 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/ConstructCategoryBarFingerprint.kt @@ -5,19 +5,19 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal object CompactHeaderConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, +internal object ConstructCategoryBarFingerprint : MethodFingerprint( + "V", + AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + listOf("Landroid/content/Context;", "L", "L", "L"), + listOf( Opcode.IPUT_OBJECT, Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, + Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST - ) + Opcode.IPUT_OBJECT, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + ), ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt index 2b692d26..f2ec3352 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/MinimizedPlaybackPatch.kt @@ -1,26 +1,39 @@ package app.revanced.patches.music.layout.minimizedplayback -import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint - +import app.revanced.patches.music.layout.minimizedplayback.fingerprints.BackgroundPlaybackDisableFingerprint +import app.revanced.patches.music.layout.minimizedplayback.fingerprints.KidsMinimizedPlaybackPolicyControllerFingerprint +import app.revanced.util.exception @Patch( - name = "Minimized playback music", - description = "Enables minimized playback on Kids music.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] + name = "Minimized playback", + description = "Unlocks options for picture-in-picture and background playback.", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object MinimizedPlaybackPatch : BytecodePatch(setOf(MinimizedPlaybackManagerFingerprint)) { - override fun execute(context: BytecodeContext) = - MinimizedPlaybackManagerFingerprint.result?.mutableMethod?.addInstruction( +object MinimizedPlaybackPatch : BytecodePatch( + setOf( + KidsMinimizedPlaybackPolicyControllerFingerprint, + BackgroundPlaybackDisableFingerprint, + ), +) { + override fun execute(context: BytecodeContext) { + KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction( + 0, + "return-void", + ) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception + + BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions( 0, """ - return-void - """ - ) ?: throw MinimizedPlaybackManagerFingerprint.exception + const/4 v0, 0x1 + return v0 + """, + ) ?: throw BackgroundPlaybackDisableFingerprint.exception + } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt new file mode 100644 index 00000000..d1341028 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/BackgroundPlaybackDisableFingerprint.kt @@ -0,0 +1,23 @@ +package app.revanced.patches.music.layout.minimizedplayback.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 BackgroundPlaybackDisableFingerprint : MethodFingerprint( + "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, + ), +) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt similarity index 87% rename from src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt index bfa47932..da6823c8 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/KidsMinimizedPlaybackPolicyControllerFingerprint.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode -internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint( +internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerprint( "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("I", "L", "Z"), @@ -22,5 +22,5 @@ internal object MinimizedPlaybackManagerFingerprint : MethodFingerprint( Opcode.CONST_4, Opcode.IF_NE, Opcode.IPUT_BOOLEAN, - ) + ), ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt index ac7827ff..4be4470d 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/HideGetPremiumPatch.kt @@ -2,41 +2,44 @@ package app.revanced.patches.music.layout.premium import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint -import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction @Patch( - name = "Hide get premium", - description = "Removes all \"Get Premium\" evidences from the avatar menu.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] + name = "Hide 'Get Music Premium' label", + description = "Hides the red \"Get Music Premium\" label from the account menu.", + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") -object HideGetPremiumPatch : BytecodePatch(setOf(HideGetPremiumParentFingerprint)) { +object HideGetPremiumPatch : BytecodePatch( + setOf(HideGetPremiumFingerprint), +) { override fun execute(context: BytecodeContext) { - val parentResult = HideGetPremiumParentFingerprint.result!! - HideGetPremiumFingerprint.resolve(context, parentResult.classDef) + HideGetPremiumFingerprint.result?.let { + it.mutableMethod.apply { + val insertIndex = it.scanResult.patternScanResult!!.endIndex - val startIndex = parentResult.scanResult.patternScanResult!!.startIndex + val setVisibilityInstruction = getInstruction(insertIndex) + val getPremiumViewRegister = setVisibilityInstruction.registerC + val visibilityRegister = setVisibilityInstruction.registerD - val parentMethod = parentResult.mutableMethod - parentMethod.replaceInstruction( - startIndex, - """ - const/4 v1, 0x0 - """ - ) + replaceInstruction( + insertIndex, + "const/16 v$visibilityRegister, 0x8", + ) - val result = HideGetPremiumFingerprint.result!! - val method = result.mutableMethod - method.addInstruction( - startIndex, - """ - const/16 v0, 0x8 - """ - ) + addInstruction( + insertIndex + 1, + "invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " + + "Landroid/view/View;->setVisibility(I)V", + ) + } + } ?: throw HideGetPremiumFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt index 6a29e7ad..e97251de 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt @@ -6,11 +6,13 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode internal object HideGetPremiumFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + listOf(), + listOf( Opcode.IF_NEZ, Opcode.CONST_16, - Opcode.GOTO, - Opcode.NOP, - Opcode.INVOKE_VIRTUAL - ) + Opcode.INVOKE_VIRTUAL, + ), + listOf("FEmusic_history", "FEmusic_offline"), ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt deleted file mode 100644 index 3463fcfc..00000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.music.layout.premium.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 HideGetPremiumParentFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC - ), - listOf("FEmusic_history"), -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt index 7cd39e17..fed2cc6d 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/RemoveUpgradeButtonPatch.kt @@ -1,71 +1,84 @@ package app.revanced.patches.music.layout.upgradebutton import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstructions +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstructions +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.extensions.newLabel import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.smali.toInstructions import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint +import app.revanced.util.exception +import app.revanced.util.getReference import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction22t -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c - +import com.android.tools.smali.dexlib2.iface.reference.FieldReference @Patch( name = "Remove upgrade button", description = "Removes the upgrade tab from the pivot bar.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] + compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], ) @Suppress("unused") object RemoveUpgradeButtonPatch : BytecodePatch( - setOf(PivotBarConstructorFingerprint) + setOf(PivotBarConstructorFingerprint), ) { override fun execute(context: BytecodeContext) { - val result = PivotBarConstructorFingerprint.result!! - val implementation = result.mutableMethod.implementation!! + PivotBarConstructorFingerprint.result?.let { + it.mutableMethod.apply { + val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1) + .getReference() - val pivotBarElementFieldRef = - (implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference + val register = (getInstructions().first() as Instruction35c).registerC - val register = (implementation.instructions.first() as Instruction35c).registerC - // first compile all the needed instructions - val instructionList = """ - invoke-interface { v0 }, Ljava/util/List;->size()I - move-result v1 - const/4 v2, 0x4 - invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; - iput-object v0, v$register, $pivotBarElementFieldRef - """.toInstructions().toMutableList() + // First compile all the needed instructions. + val instructionList = """ + invoke-interface { v0 }, Ljava/util/List;->size()I + move-result v1 + const/4 v2, 0x4 + invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; + iput-object v0, v$register, $pivotBarElementFieldReference + """.toInstructions().toMutableList() + val endIndex = it.scanResult.patternScanResult!!.endIndex - val endIndex = result.scanResult.patternScanResult!!.endIndex + // Replace the instruction to retain the label at given index. + replaceInstruction( + endIndex - 1, + instructionList[0], // invoke-interface. + ) + // Do not forget to remove this instruction since we added it already. + instructionList.removeFirst() - // replace the instruction to retain the label at given index - implementation.replaceInstruction( - endIndex - 1, instructionList[0] // invoke-interface - ) - // do not forget to remove this instruction since we added it already - instructionList.removeFirst() + val exitInstruction = instructionList.last() // iput-object + addInstruction( + endIndex, + exitInstruction, + ) + // Do not forget to remove this instruction since we added it already. + instructionList.removeLast() - val exitInstruction = instructionList.last() // iput-object - implementation.addInstruction( - 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( + 2, // if-le. + BuilderInstruction22t( + Opcode.IF_LE, + 1, + 2, + newLabel(endIndex), + ), + ) - // add the necessary if statement to remove the upgrade tab button in case it exists - instructionList.add( - 2, // if-le - BuilderInstruction22t( - Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(endIndex) - ) - ) - - implementation.addInstructions( - endIndex, instructionList - ) + addInstructions( + endIndex, + instructionList, + ) + } + } ?: throw PivotBarConstructorFingerprint.exception } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt index 36ec43f5..ee7ffbcb 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt @@ -1,62 +1,19 @@ package app.revanced.patches.music.layout.upgradebutton.fingerprints import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. internal object PivotBarConstructorFingerprint : MethodFingerprint( "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 - ) -) \ No newline at end of file + Opcode.RETURN_VOID, + ), +) diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt index 5850528f..a17903a2 100644 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/BackgroundPlayPatch.kt @@ -1,26 +1,12 @@ package app.revanced.patches.music.premium.backgroundplay -import app.revanced.util.exception import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.annotation.CompatiblePackage -import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint - - -@Patch( - name = "Background play", - description = "Enables playing music in the background.", - compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")] -) -@Suppress("unused") -object BackgroundPlayPatch : BytecodePatch(setOf(BackgroundPlaybackDisableFingerprint)) { - override fun execute(context: BytecodeContext) = - BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions( - 0, """ - const/4 v0, 0x1 - return v0 - """ - ) ?: throw BackgroundPlaybackDisableFingerprint.exception -} \ No newline at end of file +import app.revanced.patches.music.layout.minimizedplayback.MinimizedPlaybackPatch +@Deprecated("This patch has been merged into MinimizedPlaybackPatch.") +object BackgroundPlayPatch : BytecodePatch( + dependencies = setOf(MinimizedPlaybackPatch::class), +) { + override fun execute(context: BytecodeContext) { + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt deleted file mode 100644 index 68779590..00000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt +++ /dev/null @@ -1,43 +0,0 @@ -package app.revanced.patches.music.premium.backgroundplay.fingerprints - -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.AccessFlags -import com.android.tools.smali.dexlib2.Opcode - - -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint( - "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 - ) -) \ No newline at end of file