From b60c9d33b611bb4d5b55bb419652bc14b0309792 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 26 Apr 2022 23:10:36 +0200 Subject: [PATCH 1/6] feat: Patches for YouTube Music Signed-off-by: oSumAtrIX --- src/main/kotlin/app/revanced/patches/Index.kt | 24 +-- .../music/audio/EnableAudioOnlyPatch.kt | 128 ++++++++++++++++ .../music/layout/RemoveUpgradeTabPatch.kt | 144 ++++++++++++++++++ .../music/premium/BackgroundPlayPatch.kt | 88 +++++++++++ .../patches/{ => youtube}/ad/HomeAdsPatch.kt | 2 +- .../{ => youtube}/ad/HomePromoPatch.kt | 2 +- .../patches/{ => youtube}/ad/VideoAdsPatch.kt | 2 +- .../interaction/EnableSeekbarTappingPatch.kt | 2 +- .../layout/CreateButtonRemoverPatch.kt | 2 +- .../{ => youtube}/layout/HideReelsPatch.kt | 2 +- .../layout/MinimizedPlaybackPatch.kt | 2 +- .../layout/OldQualityLayoutPatch.kt | 2 +- .../layout/ShortsButtonRemoverPatch.kt | 5 +- .../{ => youtube}/misc/IntegrationsPatch.kt | 2 +- 14 files changed, 383 insertions(+), 24 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt rename src/main/kotlin/app/revanced/patches/{ => youtube}/ad/HomeAdsPatch.kt (99%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/ad/HomePromoPatch.kt (99%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/ad/VideoAdsPatch.kt (98%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/interaction/EnableSeekbarTappingPatch.kt (99%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/layout/CreateButtonRemoverPatch.kt (98%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/layout/HideReelsPatch.kt (98%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/layout/MinimizedPlaybackPatch.kt (98%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/layout/OldQualityLayoutPatch.kt (98%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/layout/ShortsButtonRemoverPatch.kt (95%) rename src/main/kotlin/app/revanced/patches/{ => youtube}/misc/IntegrationsPatch.kt (99%) diff --git a/src/main/kotlin/app/revanced/patches/Index.kt b/src/main/kotlin/app/revanced/patches/Index.kt index 7608653fb..063b445fc 100644 --- a/src/main/kotlin/app/revanced/patches/Index.kt +++ b/src/main/kotlin/app/revanced/patches/Index.kt @@ -1,16 +1,15 @@ package app.revanced.patches import app.revanced.patcher.patch.Patch -import app.revanced.patches.ad.HomeAdsPatch -import app.revanced.patches.ad.HomePromoPatch -import app.revanced.patches.ad.VideoAdsPatch -import app.revanced.patches.interaction.EnableSeekbarTappingPatch -import app.revanced.patches.layout.CreateButtonRemoverPatch -import app.revanced.patches.layout.ShortsButtonRemoverPatch -import app.revanced.patches.layout.HideReelsPatch -import app.revanced.patches.layout.MinimizedPlaybackPatch -import app.revanced.patches.layout.OldQualityLayoutPatch -import app.revanced.patches.misc.IntegrationsPatch +import app.revanced.patches.music.audio.EnableAudioOnlyPatch +import app.revanced.patches.music.layout.RemoveUpgradeTabPatch +import app.revanced.patches.music.premium.BackgroundPlayPatch +import app.revanced.patches.youtube.ad.HomeAdsPatch +import app.revanced.patches.youtube.ad.HomePromoPatch +import app.revanced.patches.youtube.ad.VideoAdsPatch +import app.revanced.patches.youtube.interaction.EnableSeekbarTappingPatch +import app.revanced.patches.youtube.layout.* +import app.revanced.patches.youtube.misc.IntegrationsPatch /** * Index contains all the patches. @@ -31,6 +30,9 @@ object Index { ::ShortsButtonRemoverPatch, ::HideReelsPatch, ::OldQualityLayoutPatch, - ::EnableSeekbarTappingPatch + ::EnableSeekbarTappingPatch, + ::EnableAudioOnlyPatch, + ::RemoveUpgradeTabPatch, + ::BackgroundPlayPatch ) } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt new file mode 100644 index 000000000..f1feb1453 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt @@ -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() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt new file mode 100644 index 000000000..c24c9c88e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt @@ -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;", ""), // 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() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt new file mode 100644 index 000000000..5b16cb236 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt @@ -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() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/ad/HomeAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt similarity index 99% rename from src/main/kotlin/app/revanced/patches/ad/HomeAdsPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt index a2158da7f..96b8e1558 100644 --- a/src/main/kotlin/app/revanced/patches/ad/HomeAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.ad +package app.revanced.patches.youtube.ad import app.revanced.extensions.injectHideCall import app.revanced.patcher.PatcherData diff --git a/src/main/kotlin/app/revanced/patches/ad/HomePromoPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt similarity index 99% rename from src/main/kotlin/app/revanced/patches/ad/HomePromoPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt index a8b6b8854..5c623a302 100644 --- a/src/main/kotlin/app/revanced/patches/ad/HomePromoPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.ad +package app.revanced.patches.youtube.ad import app.revanced.extensions.injectHideCall import app.revanced.patcher.PatcherData diff --git a/src/main/kotlin/app/revanced/patches/ad/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt similarity index 98% rename from src/main/kotlin/app/revanced/patches/ad/VideoAdsPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt index ad8b413e2..251419952 100644 --- a/src/main/kotlin/app/revanced/patches/ad/VideoAdsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.ad +package app.revanced.patches.youtube.ad import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.addInstructions diff --git a/src/main/kotlin/app/revanced/patches/interaction/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt similarity index 99% rename from src/main/kotlin/app/revanced/patches/interaction/EnableSeekbarTappingPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt index dedf0d4dc..50a238b9b 100644 --- a/src/main/kotlin/app/revanced/patches/interaction/EnableSeekbarTappingPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.interaction +package app.revanced.patches.youtube.interaction import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.addInstructions diff --git a/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt similarity index 98% rename from src/main/kotlin/app/revanced/patches/layout/CreateButtonRemoverPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt index d945f8e79..2302ed7ec 100644 --- a/src/main/kotlin/app/revanced/patches/layout/CreateButtonRemoverPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.layout +package app.revanced.patches.youtube.layout import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.or diff --git a/src/main/kotlin/app/revanced/patches/layout/HideReelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt similarity index 98% rename from src/main/kotlin/app/revanced/patches/layout/HideReelsPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt index 7ae117dc8..f846da1fd 100644 --- a/src/main/kotlin/app/revanced/patches/layout/HideReelsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.layout +package app.revanced.patches.youtube.layout import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.or diff --git a/src/main/kotlin/app/revanced/patches/layout/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt similarity index 98% rename from src/main/kotlin/app/revanced/patches/layout/MinimizedPlaybackPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt index 0bbf7645f..42c36585d 100644 --- a/src/main/kotlin/app/revanced/patches/layout/MinimizedPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.layout +package app.revanced.patches.youtube.layout import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.addInstructions diff --git a/src/main/kotlin/app/revanced/patches/layout/OldQualityLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt similarity index 98% rename from src/main/kotlin/app/revanced/patches/layout/OldQualityLayoutPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt index a69c00718..00dcdd3fd 100644 --- a/src/main/kotlin/app/revanced/patches/layout/OldQualityLayoutPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.layout +package app.revanced.patches.youtube.layout import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.addInstructions diff --git a/src/main/kotlin/app/revanced/patches/layout/ShortsButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt similarity index 95% rename from src/main/kotlin/app/revanced/patches/layout/ShortsButtonRemoverPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt index 318620516..3402c2a40 100644 --- a/src/main/kotlin/app/revanced/patches/layout/ShortsButtonRemoverPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.layout +package app.revanced.patches.youtube.layout import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.or @@ -10,10 +10,7 @@ import app.revanced.patcher.signature.PatternScanMethod import app.revanced.patcher.smali.toInstruction import org.jf.dexlib2.AccessFlags 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.builder.instruction.BuilderInstruction32x private val compatiblePackages = listOf( PackageMetadata( diff --git a/src/main/kotlin/app/revanced/patches/misc/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt similarity index 99% rename from src/main/kotlin/app/revanced/patches/misc/IntegrationsPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt index 109da2e76..931838ffc 100644 --- a/src/main/kotlin/app/revanced/patches/misc/IntegrationsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.misc +package app.revanced.patches.youtube.misc import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.addInstructions From e5fd7cece94b1ff5342178f59b29576db806e0f6 Mon Sep 17 00:00:00 2001 From: epicsampler <102923070+epicsampler@users.noreply.github.com> Date: Tue, 26 Apr 2022 21:44:02 +0000 Subject: [PATCH 2/6] feat: added `codecs-unlock` patch --- src/main/kotlin/app/revanced/patches/Index.kt | 5 +- .../patches/music/audio/CodecsUnlockPatch.kt | 153 ++++++++++++++++++ 2 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/Index.kt b/src/main/kotlin/app/revanced/patches/Index.kt index 063b445fc..55ce0e282 100644 --- a/src/main/kotlin/app/revanced/patches/Index.kt +++ b/src/main/kotlin/app/revanced/patches/Index.kt @@ -33,6 +33,7 @@ object Index { ::EnableSeekbarTappingPatch, ::EnableAudioOnlyPatch, ::RemoveUpgradeTabPatch, - ::BackgroundPlayPatch + ::BackgroundPlayPatch, + ::CodecsUnlockPatch ) -} \ No newline at end of file +} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt new file mode 100644 index 000000000..6323ff3e4 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt @@ -0,0 +1,153 @@ +package app.revanced.patches + +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 app.revanced.patcher.toMethodWalker +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +private val packageMetadata = listOf( + PackageMetadata( + "com.google.android.apps.youtube.music", + listOf("5.03.50") + ) +) + +private val patchMetadata = PatchMetadata( + "codecs-unlock", + "Audio codecs unlock patch", + "Patch to unlock more audio codecs", + packageMetadata, + "0.0.1" +) + +class CodecsUnlockPatch : Patch( + patchMetadata, + listOf( + MethodSignature( + MethodSignatureMetadata( + "codec-lock-method", + MethodMetadata( + "Labwj;", + "a", + ), + PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value. + packageMetadata, + "Required signature for ${patchMetadata.name}. Discovered in version 5.03.50.", + "0.0.1" + ), + "L", + AccessFlags.PUBLIC or AccessFlags.STATIC, + listOf("L", "L", "L", "L"), + listOf( + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_DIRECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.SGET, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_INTERFACE, + Opcode.INVOKE_DIRECT, + Opcode.RETURN_OBJECT + ) + ), + MethodSignature( + MethodSignatureMetadata( + "all-codecs-reference-method", + MethodMetadata( + "Laari;", + "b", + ), + PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value. + packageMetadata, + "Required signature for ${patchMetadata.name}. Discovered in version 5.03.50.", + "0.0.1" + ), + "J", + AccessFlags.PUBLIC or AccessFlags.FINAL, + listOf("L"), + listOf( + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.CONST_4, + Opcode.IF_EQZ, + Opcode.IGET_BOOLEAN, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.IPUT_BOOLEAN, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.GOTO, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_NEZ, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.IGET_BOOLEAN, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.IPUT_BOOLEAN, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.GOTO, + Opcode.MOVE_EXCEPTION, + Opcode.INVOKE_SUPER, + Opcode.MOVE_RESULT_WIDE, + Opcode.RETURN_WIDE + ), + listOf("itag") + ) + ) +) { + override fun execute(patcherData: PatcherData): PatchResult { + var result = signatures.first().result!! + + val implementation = result.method.implementation!! + + val instructionIndex = result.scanData.startIndex + + result = signatures.last().result!! + val codecMethod = patcherData + .toMethodWalker(result.immutableMethod) + .walk(result.scanData.startIndex) + .getMethod() + + implementation.replaceInstruction( + instructionIndex, + "invoke-static {}, ${codecMethod.definingClass}->${codecMethod.name}()Ljava/util/Set;".toInstruction() + ) + + return PatchResultSuccess() + } +} From 518229031ceca049ad790f7b77b19405d39f0ce1 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 27 Apr 2022 03:06:52 +0200 Subject: [PATCH 3/6] fix: wrong patches in `upgrade-tab-remover` Signed-off-by: oSumAtrIX --- .../patches/music/layout/RemoveUpgradeTabPatch.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt index c24c9c88e..0c618824e 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt @@ -13,6 +13,7 @@ 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 +import org.jf.dexlib2.iface.instruction.formats.Instruction35c private val compatiblePackages = listOf( PackageMetadata( @@ -99,15 +100,15 @@ class RemoveUpgradeTabPatch : Patch( val pivotBarElementFieldRef = (implementation.instructions[result.scanData.endIndex - 1] as Instruction22c).reference + 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, 0x3 - const/4 v1, 0x3 - invoke-interface {v0, v1}, Ljava/util/List;->remove(I)Ljava/lang/Object; - iput-object v0, p0, $pivotBarElementFieldRef + invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; + iput-object v0, v$register, $pivotBarElementFieldRef """.trimIndent().toInstructions().toMutableList() @@ -116,6 +117,8 @@ class RemoveUpgradeTabPatch : Patch( result.scanData.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 implementation.addInstruction( @@ -127,7 +130,7 @@ class RemoveUpgradeTabPatch : Patch( // add the necessary if statement to remove the upgrade tab button in case it exists instructionList.add( - 3, // if-le + 2, // if-le BuilderInstruction22t( Opcode.IF_LE, 1, 2, From b299205aa7cde82f1f55fc598de3ff8d80b8bcb0 Mon Sep 17 00:00:00 2001 From: epicsampler <102923070+epicsampler@users.noreply.github.com> Date: Thu, 28 Apr 2022 15:02:57 +0000 Subject: [PATCH 4/6] fix: version in package metadata of music --- .../app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt | 2 +- .../app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt | 2 +- .../app/revanced/patches/music/premium/BackgroundPlayPatch.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt index f1feb1453..2227de927 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt @@ -14,7 +14,7 @@ import org.jf.dexlib2.Opcode private val compatiblePackages = listOf( PackageMetadata( "com.google.android.apps.youtube.music", - listOf("05.03.50") + listOf("5.03.50") ) ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt index 0c618824e..18afabb9a 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt @@ -18,7 +18,7 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c private val compatiblePackages = listOf( PackageMetadata( "com.google.android.apps.youtube.music", - listOf("05.03.50") + listOf("5.03.50") ) ) diff --git a/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt index 5b16cb236..a6698e127 100644 --- a/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt @@ -15,7 +15,7 @@ import org.jf.dexlib2.Opcode private val compatiblePackages = listOf( PackageMetadata( "com.google.android.apps.youtube.music", - listOf("05.03.50") + listOf("5.03.50") ) ) From a6aeca31bd80b8c4a8acd071e22faca6e136bdb0 Mon Sep 17 00:00:00 2001 From: epicsampler <102923070+epicsampler@users.noreply.github.com> Date: Thu, 28 Apr 2022 15:47:08 +0000 Subject: [PATCH 5/6] feat: `tastebuilder-remover` for music --- src/main/kotlin/app/revanced/patches/Index.kt | 2 + .../music/layout/RemoveTastebuilderPatch.kt | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/Index.kt b/src/main/kotlin/app/revanced/patches/Index.kt index 55ce0e282..6aacc9a78 100644 --- a/src/main/kotlin/app/revanced/patches/Index.kt +++ b/src/main/kotlin/app/revanced/patches/Index.kt @@ -3,6 +3,7 @@ package app.revanced.patches import app.revanced.patcher.patch.Patch import app.revanced.patches.music.audio.EnableAudioOnlyPatch import app.revanced.patches.music.layout.RemoveUpgradeTabPatch +import app.revanced.patches.music.layout.RemoveTastebuilderPatch import app.revanced.patches.music.premium.BackgroundPlayPatch import app.revanced.patches.youtube.ad.HomeAdsPatch import app.revanced.patches.youtube.ad.HomePromoPatch @@ -33,6 +34,7 @@ object Index { ::EnableSeekbarTappingPatch, ::EnableAudioOnlyPatch, ::RemoveUpgradeTabPatch, + ::RemoveTastebuilderPatch, ::BackgroundPlayPatch, ::CodecsUnlockPatch ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt new file mode 100644 index 000000000..723ba6a09 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt @@ -0,0 +1,80 @@ +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.iface.instruction.formats.Instruction22c + +private val compatiblePackages = listOf( + PackageMetadata( + "com.google.android.apps.youtube.music", + listOf("5.03.50") + ) +) + +class RemoveTastebuilderPatch : Patch( + PatchMetadata( + "tastebuilder-remover", + "Remove Tastebuilder Patch", + "Remove the tastebuilder from the Home screen.", + compatiblePackages, + "0.0.1" + ), + listOf( + MethodSignature( + MethodSignatureMetadata( + "tastebuilder-constructor", + MethodMetadata("Lkyu;", ""), + 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", "L", "L", "L"), + listOf( + Opcode.INVOKE_DIRECT, + Opcode.INVOKE_VIRTUAL, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IPUT_OBJECT + ) + ) + ) +) { + override fun execute(patcherData: PatcherData): PatchResult { + val result = signatures.first().result!! + val implementation = result.method.implementation!! + + val register = (implementation.instructions[result.scanData.endIndex] as Instruction22c).registerA + + val instructionList = + """ + const/16 v1, 0x8 + invoke-virtual {v${register}, v1}, Landroid/view/View;->setVisibility(I)V + """.trimIndent().toInstructions().toMutableList() + + implementation.addInstructions( + result.scanData.endIndex, + instructionList + ) + + return PatchResultSuccess() + } +} From 8ea34036e54b8bc80ea83c4912c800243aa128cb Mon Sep 17 00:00:00 2001 From: epicsampler <102923070+epicsampler@users.noreply.github.com> Date: Thu, 28 Apr 2022 15:50:43 +0000 Subject: [PATCH 6/6] refactor: YouTube Music patches --- src/main/kotlin/app/revanced/patches/Index.kt | 5 ++-- .../patches/music/audio/CodecsUnlockPatch.kt | 4 ++-- ...derPatch.kt => RemoveTasteBuilderPatch.kt} | 24 +++++++++++++------ 3 files changed, 22 insertions(+), 11 deletions(-) rename src/main/kotlin/app/revanced/patches/music/layout/{RemoveTastebuilderPatch.kt => RemoveTasteBuilderPatch.kt} (75%) diff --git a/src/main/kotlin/app/revanced/patches/Index.kt b/src/main/kotlin/app/revanced/patches/Index.kt index 6aacc9a78..f55a8b013 100644 --- a/src/main/kotlin/app/revanced/patches/Index.kt +++ b/src/main/kotlin/app/revanced/patches/Index.kt @@ -3,8 +3,9 @@ package app.revanced.patches import app.revanced.patcher.patch.Patch import app.revanced.patches.music.audio.EnableAudioOnlyPatch import app.revanced.patches.music.layout.RemoveUpgradeTabPatch -import app.revanced.patches.music.layout.RemoveTastebuilderPatch +import app.revanced.patches.music.layout.RemoveTasteBuilderPatch import app.revanced.patches.music.premium.BackgroundPlayPatch +import app.revanced.patches.music.audio.CodecsUnlockPatch import app.revanced.patches.youtube.ad.HomeAdsPatch import app.revanced.patches.youtube.ad.HomePromoPatch import app.revanced.patches.youtube.ad.VideoAdsPatch @@ -34,7 +35,7 @@ object Index { ::EnableSeekbarTappingPatch, ::EnableAudioOnlyPatch, ::RemoveUpgradeTabPatch, - ::RemoveTastebuilderPatch, + ::RemoveTasteBuilderPatch, ::BackgroundPlayPatch, ::CodecsUnlockPatch ) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt index 6323ff3e4..df24b4de5 100644 --- a/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt @@ -1,4 +1,4 @@ -package app.revanced.patches +package app.revanced.patches.music.audio import app.revanced.patcher.PatcherData import app.revanced.patcher.extensions.or @@ -22,7 +22,7 @@ private val packageMetadata = listOf( private val patchMetadata = PatchMetadata( "codecs-unlock", "Audio codecs unlock patch", - "Patch to unlock more audio codecs", + "Enables more audio codecs. Usually results in better audio quality but may depend on song and device.", packageMetadata, "0.0.1" ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt similarity index 75% rename from src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt rename to src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt index 723ba6a09..de03987e0 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/RemoveTastebuilderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt @@ -20,18 +20,18 @@ private val compatiblePackages = listOf( ) ) -class RemoveTastebuilderPatch : Patch( +class RemoveTasteBuilderPatch : Patch( PatchMetadata( - "tastebuilder-remover", - "Remove Tastebuilder Patch", - "Remove the tastebuilder from the Home screen.", + "tasteBuilder-remover", + "Remove TasteBuilder Patch", + "Removes the \"Tell us which artists you like\" card from the Home screen. The same functionality can be triggered from the settings anyway.", compatiblePackages, "0.0.1" ), listOf( MethodSignature( MethodSignatureMetadata( - "tastebuilder-constructor", + "taste-builder-constructor", MethodMetadata("Lkyu;", ""), PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. compatiblePackages, @@ -53,6 +53,14 @@ class RemoveTastebuilderPatch : Patch( Opcode.CONST_4, Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.IPUT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, Opcode.IPUT_OBJECT ) ) @@ -62,7 +70,9 @@ class RemoveTastebuilderPatch : Patch( val result = signatures.first().result!! val implementation = result.method.implementation!! - val register = (implementation.instructions[result.scanData.endIndex] as Instruction22c).registerA + val insertIndex = result.scanData.endIndex - 8 + + val register = (implementation.instructions[insertIndex] as Instruction22c).registerA val instructionList = """ @@ -71,7 +81,7 @@ class RemoveTastebuilderPatch : Patch( """.trimIndent().toInstructions().toMutableList() implementation.addInstructions( - result.scanData.endIndex, + insertIndex, instructionList )