diff --git a/build.gradle.kts b/build.gradle.kts index a26bfa0de..13e62633b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation("app.revanced:revanced-patcher:7.0.0") + implementation("app.revanced:revanced-patcher:7.1.1") implementation("app.revanced:multidexlib2:2.5.3-a3836654") // Required for meta implementation("com.google.code.gson:gson:2.10.1") diff --git a/src/main/kotlin/app/revanced/patches/music/layout/autocaptions/patch/DisableAutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/autocaptions/patch/DisableAutoCaptionsPatch.kt index 49fc84768..7a55a0eea 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/autocaptions/patch/DisableAutoCaptionsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/autocaptions/patch/DisableAutoCaptionsPatch.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.* import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess @@ -25,23 +25,19 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @YouTubeMusicCompatibility @Version("0.0.1") class DisableAutoCaptionsPatch : BytecodePatch( - listOf( - SubtitleTrackFingerprint - ) + listOf(SubtitleTrackFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { SubtitleTrackFingerprint.result?.mutableMethod?.let { - with (it.implementation!!.instructions) { - val index = size - 1 - val register = (elementAt(index) as OneRegisterInstruction).registerA - it.addInstructions( - index, """ + val index = it.implementation!!.instructions.size - 1 + val register = it.instruction(index).registerA + it.addInstructions( + index, """ invoke-static {v$register}, $MUSIC_LAYOUT->disableAutoCaptions(Z)Z move-result v$register """ - ) - } + ) } ?: return SubtitleTrackFingerprint.toErrorResult() MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_disable_auto_captions", "false") diff --git a/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/fingerprints/TabLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/fingerprints/TabLayoutFingerprint.kt index c21fedff1..2608de072 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/fingerprints/TabLayoutFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/fingerprints/TabLayoutFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.music.layout.blacknavbar.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.colorGreyId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -16,11 +16,6 @@ object TabLayoutFingerprint : MethodFingerprint( Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.colorGreyLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(colorGreyId) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/patch/BlackNavbarPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/patch/BlackNavbarPatch.kt index 8d8077805..d7a5c2985 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/patch/BlackNavbarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/blacknavbar/patch/BlackNavbarPatch.kt @@ -18,7 +18,7 @@ import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatc import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.util.enum.CategoryType import app.revanced.util.integrations.Constants.MUSIC_LAYOUT -import org.jf.dexlib2.iface.instruction.formats.Instruction11x +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @Patch @Name("enable-black-navbar") @@ -32,21 +32,17 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction11x @YouTubeMusicCompatibility @Version("0.0.1") class BlackNavbarPatch : BytecodePatch( - listOf( - TabLayoutFingerprint - ) + listOf(TabLayoutFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { TabLayoutFingerprint.result?.let { - with (it.mutableMethod) { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val insertIndex = endIndex + 1 - - val targetRegister = (instruction(endIndex) as Instruction11x).registerA + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = instruction(targetIndex).registerA addInstructions( - insertIndex, """ + targetIndex + 1, """ invoke-static {}, $MUSIC_LAYOUT->enableBlackNavbar()I move-result v$targetRegister """ diff --git a/src/main/kotlin/app/revanced/patches/music/layout/castbutton/patch/HideCastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/castbutton/patch/HideCastButtonPatch.kt index 105b701c0..a1a91fc5c 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/castbutton/patch/HideCastButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/castbutton/patch/HideCastButtonPatch.kt @@ -25,9 +25,7 @@ import app.revanced.util.integrations.Constants.MUSIC_LAYOUT @YouTubeMusicCompatibility @Version("0.0.1") class HideCastButtonPatch : BytecodePatch( - listOf( - HideCastButtonParentFingerprint - ) + listOf(HideCastButtonParentFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/music/layout/categorybar/fingerprints/ChipCloudFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/categorybar/fingerprints/ChipCloudFingerprint.kt new file mode 100644 index 000000000..5c043c51a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/categorybar/fingerprints/ChipCloudFingerprint.kt @@ -0,0 +1,18 @@ +package app.revanced.patches.music.layout.categorybar.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.chipCloudId +import app.revanced.util.bytecode.isWideLiteralExists +import org.jf.dexlib2.Opcode + +object ChipCloudFingerprint : MethodFingerprint( + returnType = "V", + opcodes = listOf( + Opcode.CONST, + Opcode.CONST_4, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT + ), + customFingerprint = { it.isWideLiteralExists(chipCloudId) } +) + diff --git a/src/main/kotlin/app/revanced/patches/music/layout/categorybar/patch/CategoryBarPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/categorybar/patch/CategoryBarPatch.kt index 352379473..78c0c5faa 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/categorybar/patch/CategoryBarPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/categorybar/patch/CategoryBarPatch.kt @@ -1,82 +1,54 @@ package app.revanced.patches.music.layout.categorybar.patch -import app.revanced.extensions.findMutableMethodOf -import app.revanced.extensions.toResult +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.extensions.instruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patches.music.layout.categorybar.fingerprints.ChipCloudFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatch import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch import app.revanced.util.enum.CategoryType import app.revanced.util.integrations.Constants.MUSIC_LAYOUT -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.Instruction21c -import org.jf.dexlib2.iface.instruction.formats.Instruction31i +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @Patch @Name("hide-category-bar") @Description("Hides the music category bar at the top of the homepage.") @DependsOn( [ - ResourceMappingPatch::class, + SharedResourceIdPatch::class, MusicSettingsPatch::class ] ) @YouTubeMusicCompatibility @Version("0.0.1") -class CategoryBarPatch : BytecodePatch() { - - // list of resource names to get the id of - private val resourceIds = arrayOf( - "layout" to "chip_cloud" - ).map { (type, name) -> - ResourceMappingPatch - .resourceMappings - .single { it.type == type && it.name == name }.id - } - private var patchSuccessArray = Array(resourceIds.size) {false} - +class CategoryBarPatch : BytecodePatch( + listOf(ChipCloudFingerprint) +) { override fun execute(context: BytecodeContext): PatchResult { - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - with(method.implementation) { - this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { // compact header - val insertIndex = index + 4 - val invokeInstruction = instructions.elementAt(insertIndex) - if (invokeInstruction.opcode != Opcode.CHECK_CAST) return@forEachIndexed + ChipCloudFingerprint.result?.let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = instruction(targetIndex).registerA - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) - - val register = (invokeInstruction as Instruction21c).registerA - - mutableMethod.addInstruction( - insertIndex, - "invoke-static { v$register }, $MUSIC_LAYOUT->hideCategoryBar(Landroid/view/View;)V" - ) - - MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_hide_category_bar", "true") - - patchSuccessArray[0] = true - } - } - } - else -> return@forEachIndexed - } - } - } + addInstruction( + targetIndex + 1, + "invoke-static { v$targetRegister }, $MUSIC_LAYOUT->hideCategoryBar(Landroid/view/View;)V" + ) } - } - return toResult(patchSuccessArray.indexOf(false)) + } ?: return ChipCloudFingerprint.toErrorResult() + + MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_hide_category_bar", "true") + + return PatchResultSuccess() } } diff --git a/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/fingerprints/MiniplayerColorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/fingerprints/ColorMatchPlayerFingerprint.kt similarity index 75% rename from src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/fingerprints/MiniplayerColorFingerprint.kt rename to src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/fingerprints/ColorMatchPlayerFingerprint.kt index 126fcd630..d7f65cbab 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/fingerprints/MiniplayerColorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/fingerprints/ColorMatchPlayerFingerprint.kt @@ -1,11 +1,11 @@ -package app.revanced.patches.music.layout.miniplayercolor.fingerprints +package app.revanced.patches.music.layout.colormatchplayer.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode -object MiniplayerColorFingerprint : MethodFingerprint( +object ColorMatchPlayerFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PUBLIC or AccessFlags.FINAL, parameters = listOf("L", "J"), diff --git a/src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/patch/ColorMatchPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/patch/ColorMatchPlayerPatch.kt new file mode 100644 index 000000000..aadecae8a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/colormatchplayer/patch/ColorMatchPlayerPatch.kt @@ -0,0 +1,86 @@ +package app.revanced.patches.music.layout.colormatchplayer.patch + +import app.revanced.extensions.toErrorResult +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.extensions.removeInstruction +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.PatchResult +import app.revanced.patcher.patch.PatchResultSuccess +import app.revanced.patcher.patch.annotations.DependsOn +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patcher.util.smali.ExternalLabel +import app.revanced.patches.music.layout.colormatchplayer.fingerprints.ColorMatchPlayerFingerprint +import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatch +import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility +import app.revanced.patches.shared.fingerprints.ColorMatchPlayerParentFingerprint +import app.revanced.util.enum.CategoryType +import app.revanced.util.integrations.Constants.MUSIC_LAYOUT +import org.jf.dexlib2.iface.instruction.Instruction +import org.jf.dexlib2.iface.instruction.ReferenceInstruction + +@Patch +@Name("enable-color-match-player") +@Description("Matches the fullscreen player color with the minimized one.") +@DependsOn([MusicSettingsPatch::class]) +@YouTubeMusicCompatibility +@Version("0.0.1") +class ColorMatchPlayerPatch : BytecodePatch( + listOf(ColorMatchPlayerParentFingerprint) +) { + override fun execute(context: BytecodeContext): PatchResult { + + ColorMatchPlayerParentFingerprint.result?.let { parentResult -> + ColorMatchPlayerFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { + it.mutableMethod.apply { + targetMethod = parentResult.mutableMethod + + val insertIndex = it.scanResult.patternScanResult!!.startIndex + 1 + val jumpInstruction = instruction(insertIndex) + + val type = it.classDef.type + + addInstructions( + insertIndex, """ + invoke-static {}, $MUSIC_LAYOUT->enableColorMatchPlayer()Z + move-result v2 + if-eqz v2, :off + iget v0, p0, ${descriptor(4)} + if-eq v0, v2, :abswitch + iput v2, p0, ${descriptor(4)} + iget-object v0, p0, ${descriptor(5)} + invoke-virtual {v0, v2, p2, p3}, ${descriptor(6)} + :abswitch + iget v0, p0, ${descriptor(10)} + if-eq v0, v1, :exit + iput v1, p0, ${descriptor(10)} + iget-object v0, p0, ${descriptor(11)} + invoke-virtual {v0, v1, p2, p3}, ${descriptor(12)} + goto :exit + :off + invoke-direct {p0}, ${type}->${parentResult.mutableMethod.name}()V + """, listOf(ExternalLabel("exit", jumpInstruction)) + ) + removeInstruction(insertIndex - 1) + } + } ?: return ColorMatchPlayerFingerprint.toErrorResult() + } ?: return ColorMatchPlayerParentFingerprint.toErrorResult() + + MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_enable_color_match_player", "true") + + return PatchResultSuccess() + } + private companion object { + private lateinit var targetMethod: MutableMethod + + fun descriptor(index: Int):String { + return (targetMethod.instruction(index) as ReferenceInstruction).reference.toString() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/fingerprints/DialogSolidFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/fingerprints/DialogSolidFingerprint.kt index b54b1a61d..ae358cc3d 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/fingerprints/DialogSolidFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/fingerprints/DialogSolidFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.music.layout.compactdialog.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.dialogSolidId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -16,11 +16,6 @@ object DialogSolidFingerprint : MethodFingerprint( Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_STATIC ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.dialogSolidLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(dialogSolidId) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/patch/CompactDialogPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/patch/CompactDialogPatch.kt index 4b89328d4..031569b03 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/patch/CompactDialogPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/compactdialog/patch/CompactDialogPatch.kt @@ -20,6 +20,7 @@ import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.util.enum.CategoryType import app.revanced.util.integrations.Constants.MUSIC_LAYOUT + @Patch @Name("enable-compact-dialog") @Description("Enable compact dialog on phone.") @@ -32,9 +33,7 @@ import app.revanced.util.integrations.Constants.MUSIC_LAYOUT @YouTubeMusicCompatibility @Version("0.0.1") class CompactDialogPatch : BytecodePatch( - listOf( - DialogSolidFingerprint - ) + listOf(DialogSolidFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { DialogSolidFingerprint.result?.let { diff --git a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonParentFingerprint.kt index b19f0cd25..8f24b95b9 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonParentFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/fingerprints/FloatingButtonParentFingerprint.kt @@ -2,19 +2,15 @@ package app.revanced.patches.music.layout.floatingbutton.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.util.bytecode.isNarrowLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction object FloatingButtonParentFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PROTECTED or AccessFlags.FINAL, parameters = listOf("L"), opcodes = listOf(Opcode.INVOKE_DIRECT), - customFingerprint = { methodDef -> - methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 259982244) - } - } + customFingerprint = { it.isNarrowLiteralExists(259982244) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt index cc5403074..0c88963a8 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/floatingbutton/patch/NewPlaylistButtonPatch.kt @@ -33,9 +33,7 @@ import app.revanced.util.integrations.Constants.MUSIC_LAYOUT @YouTubeMusicCompatibility @Version("0.0.1") class NewPlaylistButtonPatch : BytecodePatch( - listOf( - FloatingButtonParentFingerprint - ) + listOf(FloatingButtonParentFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/fingerprints/TabletIdentifierFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/fingerprints/TabletIdentifierFingerprint.kt index 2b118f85c..e58719aa0 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/fingerprints/TabletIdentifierFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/fingerprints/TabletIdentifierFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.music.layout.landscapemode.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.isTabletId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -16,11 +16,6 @@ object TabletIdentifierFingerprint : MethodFingerprint( Opcode.INVOKE_VIRTUAL, Opcode.MOVE_RESULT ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.isTabletLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(isTabletId) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/patch/LandScapeModePatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/patch/LandScapeModePatch.kt index b20bcf5cb..f1763186b 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/patch/LandScapeModePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/landscapemode/patch/LandScapeModePatch.kt @@ -30,18 +30,16 @@ import app.revanced.util.integrations.Constants.MUSIC_LAYOUT @YouTubeMusicCompatibility @Version("0.0.1") class LandScapeModePatch : BytecodePatch( - listOf( - TabletIdentifierFingerprint - ) + listOf(TabletIdentifierFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { TabletIdentifierFingerprint.result?.let { it.mutableMethod.addInstructions( it.scanResult.patternScanResult!!.endIndex + 1, """ - invoke-static {p0}, $MUSIC_LAYOUT->enableLandScapeMode(Z)Z - move-result p0 - """ - ) + invoke-static {p0}, $MUSIC_LAYOUT->enableLandScapeMode(Z)Z + move-result p0 + """ + ) } ?: return TabletIdentifierFingerprint.toErrorResult() MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_enable_landscape_mode", "true") diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayer/patch/MinimizedPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayer/patch/MinimizedPlayerPatch.kt index 0effa0676..0b066bdc8 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayer/patch/MinimizedPlayerPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayer/patch/MinimizedPlayerPatch.kt @@ -25,9 +25,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @YouTubeMusicCompatibility @Version("0.0.1") class MinimizedPlayerPatch : BytecodePatch( - listOf( - MinimizedPlayerFingerprint - ) + listOf(MinimizedPlayerFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/patch/MiniplayerColorPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/patch/MiniplayerColorPatch.kt deleted file mode 100644 index 97730f955..000000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/miniplayercolor/patch/MiniplayerColorPatch.kt +++ /dev/null @@ -1,109 +0,0 @@ -package app.revanced.patches.music.layout.miniplayercolor.patch - -import app.revanced.extensions.toErrorResult -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.music.layout.miniplayercolor.fingerprints.MiniplayerColorFingerprint -import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatch -import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility -import app.revanced.patches.shared.fingerprints.MiniplayerColorParentFingerprint -import app.revanced.util.enum.CategoryType -import app.revanced.util.integrations.Constants.MUSIC_LAYOUT -import org.jf.dexlib2.iface.instruction.Instruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference - -@Patch -@Name("enable-color-match-player") -@Description("Matches the fullscreen player color with the minimized one.") -@DependsOn([MusicSettingsPatch::class]) -@YouTubeMusicCompatibility -@Version("0.0.1") -class MiniplayerColorPatch : BytecodePatch( - listOf( - MiniplayerColorFingerprint, MiniplayerColorParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - - MiniplayerColorParentFingerprint.result?.let { parentResult -> - - with (parentResult.mutableMethod.implementation!!.instructions) { - firstReference = - (elementAt(4) as ReferenceInstruction).reference as FieldReference - - secondReference = - (elementAt(5) as ReferenceInstruction).reference as FieldReference - - thirdReference = - (elementAt(6) as ReferenceInstruction).reference as MethodReference - - fourthReference = - (elementAt(10) as ReferenceInstruction).reference as FieldReference - - fifthReference = - (elementAt(11) as ReferenceInstruction).reference as FieldReference - - sixthReference = - (elementAt(12) as ReferenceInstruction).reference as MethodReference - } - - MiniplayerColorFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { - with (it.mutableMethod) { - val insertIndex = it.scanResult.patternScanResult!!.startIndex + 1 - val jumpInstruction = implementation!!.instructions[insertIndex] as Instruction - - val type = it.classDef.type - - addInstructions( - insertIndex, """ - invoke-static {}, $MUSIC_LAYOUT->enableColorMatchPlayer()Z - move-result v2 - if-eqz v2, :off - iget v0, p0, ${type}->${firstReference.name}:${firstReference.type} - if-eq v0, v2, :abswitch - iput v2, p0, ${type}->${firstReference.name}:${firstReference.type} - iget-object v0, p0, ${type}->${secondReference.name}:${secondReference.type} - invoke-virtual {v0, v2, p2, p3}, $thirdReference - :abswitch - iget v0, p0, ${type}->${fourthReference.name}:${fourthReference.type} - if-eq v0, v1, :exit - iput v1, p0, ${type}->${fourthReference.name}:${fourthReference.type} - iget-object v0, p0, ${type}->${fifthReference.name}:${fifthReference.type} - invoke-virtual {v0, v1, p2, p3}, $sixthReference - goto :exit - :off - invoke-direct {p0}, ${type}->${parentResult.mutableMethod.name}()V - """, listOf(ExternalLabel("exit", jumpInstruction)) - ) - removeInstruction(insertIndex - 1) - } - } ?: return MiniplayerColorFingerprint.toErrorResult() - } ?: return MiniplayerColorParentFingerprint.toErrorResult() - - MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_enable_color_match_player", "true") - - return PatchResultSuccess() - } - private companion object { - private lateinit var firstReference: FieldReference - private lateinit var secondReference: FieldReference - private lateinit var thirdReference: MethodReference - - private lateinit var fourthReference: FieldReference - private lateinit var fifthReference: FieldReference - private lateinit var sixthReference: MethodReference - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/zenmode/patch/ZenModePatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/zenmode/patch/ZenModePatch.kt index b69227964..4696467cf 100644 --- a/src/main/kotlin/app/revanced/patches/music/layout/zenmode/patch/ZenModePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/layout/zenmode/patch/ZenModePatch.kt @@ -5,7 +5,9 @@ import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.* +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.extensions.removeInstruction import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult @@ -15,12 +17,11 @@ import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.music.layout.zenmode.fingerprints.ZenModeFingerprint import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatch import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility -import app.revanced.patches.shared.fingerprints.MiniplayerColorParentFingerprint +import app.revanced.patches.shared.fingerprints.ColorMatchPlayerParentFingerprint import app.revanced.util.enum.CategoryType import app.revanced.util.integrations.Constants.MUSIC_LAYOUT import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference @Patch @Name("enable-zen-mode") @@ -29,24 +30,21 @@ import org.jf.dexlib2.iface.reference.FieldReference @YouTubeMusicCompatibility @Version("0.0.1") class ZenModePatch : BytecodePatch( - listOf( - ZenModeFingerprint, MiniplayerColorParentFingerprint - ) + listOf(ColorMatchPlayerParentFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { - MiniplayerColorParentFingerprint.result?.let { parentResult -> + ColorMatchPlayerParentFingerprint.result?.let { parentResult -> ZenModeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { - with (it.mutableMethod) { - val instructions = this.implementation!!.instructions + it.mutableMethod.apply { val startIndex = it.scanResult.patternScanResult!!.startIndex - val firstRegister = (instruction(startIndex) as OneRegisterInstruction).registerA - val secondRegister = (instruction(startIndex + 2) as OneRegisterInstruction).registerA + val firstRegister = instruction(startIndex).registerA + val secondRegister = instruction(startIndex + 2).registerA val dummyRegister = secondRegister + 1 val referenceIndex = it.scanResult.patternScanResult!!.endIndex + 1 - val fieldReference = (instructions.elementAt(referenceIndex) as ReferenceInstruction).reference as FieldReference + val targetReference = (instruction(referenceIndex) as ReferenceInstruction).reference.toString() val insertIndex = referenceIndex + 1 @@ -60,13 +58,13 @@ class ZenModePatch : BytecodePatch( const v$firstRegister, -0xbfbfc0 const v$secondRegister, -0xbfbfc0 :off - sget-object v0, ${fieldReference.type}->${fieldReference.name}:${fieldReference.type} + sget-object v0, $targetReference """ ) removeInstruction(referenceIndex) } } ?: return ZenModeFingerprint.toErrorResult() - } ?: return MiniplayerColorParentFingerprint.toErrorResult() + } ?: return ColorMatchPlayerParentFingerprint.toErrorResult() MusicSettingsPatch.addMusicPreference(CategoryType.LAYOUT, "revanced_enable_zen_mode", "false") diff --git a/src/main/kotlin/app/revanced/patches/music/misc/clientspoof/patch/ClientSpoofMusicPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/clientspoof/patch/ClientSpoofMusicPatch.kt index 14b52f9a5..9a36377a9 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/clientspoof/patch/ClientSpoofMusicPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/clientspoof/patch/ClientSpoofMusicPatch.kt @@ -25,10 +25,14 @@ class ClientSpoofMusicPatch : BytecodePatch( override fun execute(context: BytecodeContext): PatchResult { UserAgentHeaderBuilderFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val insertIndex = it.scanResult.patternScanResult!!.endIndex - 1 - val packageNameRegister = (instruction(insertIndex) as FiveRegisterInstruction).registerD - addInstruction(insertIndex, "const-string v$packageNameRegister, \"$MUSIC_PACKAGE_NAME\"") + val packageNameRegister = instruction(insertIndex).registerD + + addInstruction( + insertIndex, + "const-string v$packageNameRegister, \"$MUSIC_PACKAGE_NAME\"" + ) } } ?: return UserAgentHeaderBuilderFingerprint.toErrorResult() diff --git a/src/main/kotlin/app/revanced/patches/music/misc/codecs/patch/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/codecs/patch/CodecsUnlockPatch.kt index 2b8b9685a..b54b652a5 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/codecs/patch/CodecsUnlockPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/codecs/patch/CodecsUnlockPatch.kt @@ -38,28 +38,26 @@ class CodecsUnlockPatch : BytecodePatch( override fun execute(context: BytecodeContext): PatchResult { AllCodecsParentFingerprint.result?.let { parentResult -> - AllCodecsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> - allCodecsMethod = - context.toMethodWalker(result.method) - .nextMethod(result.scanResult.patternScanResult!!.endIndex) + AllCodecsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { + allCodecsMethod = context.toMethodWalker(it.method) + .nextMethod(it.scanResult.patternScanResult!!.endIndex) .getMethod() } ?: return AllCodecsFingerprint.toErrorResult() } ?: return AllCodecsParentFingerprint.toErrorResult() - CodecsLockFingerprint.result?.let { result -> - val endIndex = result.scanResult.patternScanResult!!.endIndex - - with(result.mutableMethod) { - val register = (instruction(endIndex) as OneRegisterInstruction).registerA + CodecsLockFingerprint.result?.let { + it.mutableMethod.apply { + val targetIndex = it.scanResult.patternScanResult!!.endIndex + val targetRegister = instruction(targetIndex).registerA addInstructions( - endIndex + 1, """ + targetIndex + 1, """ invoke-static {}, $MUSIC_MISC_PATH/OpusCodecPatch;->enableOpusCodec()Z move-result v7 if-eqz v7, :mp4a invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set; - move-result-object v$register - """, listOf(ExternalLabel("mp4a", instruction(endIndex + 1))) + move-result-object v$targetRegister + """, listOf(ExternalLabel("mp4a", instruction(targetIndex + 1))) ) } } ?: return CodecsLockFingerprint.toErrorResult() diff --git a/src/main/kotlin/app/revanced/patches/music/misc/exclusiveaudio/patch/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/exclusiveaudio/patch/ExclusiveAudioPatch.kt index 0e18e3496..6fa029c22 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/exclusiveaudio/patch/ExclusiveAudioPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/exclusiveaudio/patch/ExclusiveAudioPatch.kt @@ -20,9 +20,7 @@ import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility @YouTubeMusicCompatibility @Version("0.0.1") class ExclusiveAudioPatch : BytecodePatch( - listOf( - AudioOnlyEnablerFingerprint - ) + listOf(AudioOnlyEnablerFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/music/misc/litho/patch/MusicLithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/litho/patch/MusicLithoFilterPatch.kt index c7681ee59..659b293d0 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/litho/patch/MusicLithoFilterPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/litho/patch/MusicLithoFilterPatch.kt @@ -11,64 +11,56 @@ import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.patches.shared.fingerprints.LithoFingerprint +import app.revanced.util.bytecode.getNarrowLiteralIndex import app.revanced.util.integrations.Constants.MUSIC_ADS_PATH import org.jf.dexlib2.Opcode import org.jf.dexlib2.builder.instruction.BuilderInstruction21c import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.instruction.formats.Instruction31i import org.jf.dexlib2.iface.reference.FieldReference import org.jf.dexlib2.iface.reference.MethodReference @YouTubeMusicCompatibility @Version("0.0.1") class MusicLithoFilterPatch : BytecodePatch( - listOf( - LithoFingerprint - ) + listOf(LithoFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { - LithoFingerprint.result?.let { result -> - val endIndex = result.scanResult.patternScanResult!!.endIndex - val method = result.mutableMethod + LithoFingerprint.result?.let { + it.mutableMethod.apply { + val targetInstruction = implementation!!.instructions - with (method.implementation!!.instructions) { - val bufferIndex = indexOfFirst { - it.opcode == Opcode.CONST && - (it as Instruction31i).narrowLiteral == 168777401 - } - val bufferRegister = (method.instruction(bufferIndex) as Instruction31i).registerA - - val targetIndex = indexOfFirst { - it.opcode == Opcode.CONST_STRING && - (it as BuilderInstruction21c).reference.toString() == "Element missing type extension" + val endIndex = it.scanResult.patternScanResult!!.endIndex + val bufferIndex = getNarrowLiteralIndex(168777401) + val bufferRegister = instruction(bufferIndex).registerA + val targetIndex = targetInstruction.indexOfFirst { instruction -> + instruction.opcode == Opcode.CONST_STRING && + (instruction as BuilderInstruction21c).reference.toString() == "Element missing type extension" } + 2 - val builderMethodDescriptor = (elementAt(targetIndex) as ReferenceInstruction).reference as MethodReference - val emptyComponentFieldDescriptor = (elementAt(targetIndex + 2) as ReferenceInstruction).reference as FieldReference + val builderMethodDescriptor = (instruction(targetIndex) as ReferenceInstruction).reference as MethodReference + val emptyComponentFieldDescriptor = (instruction(targetIndex + 2) as ReferenceInstruction).reference as FieldReference + val identifierRegister = instruction(endIndex).registerA - val identifierRegister = (method.instruction(endIndex) as OneRegisterInstruction).registerA - - filter { instruction -> + targetInstruction.filter { instruction -> val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference - fieldReference?.let { it.type == "Ljava/lang/StringBuilder;" } == true + fieldReference?.let { reference -> reference.type == "Ljava/lang/StringBuilder;" } == true }.forEach { instruction -> - val insertIndex = indexOf(instruction) - val stringBuilderRegister = (method.instruction(insertIndex) as TwoRegisterInstruction).registerA + val insertIndex = targetInstruction.indexOf(instruction) + val stringBuilderRegister = instruction(insertIndex).registerA - method.addInstructions( - insertIndex, // right after setting the component.pathBuilder field, - """ - invoke-static {v$stringBuilderRegister, v$identifierRegister}, $MUSIC_ADS_PATH/MusicLithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z - move-result v$bufferRegister - if-eqz v$bufferRegister, :not_an_ad - move-object/from16 v$identifierRegister, p1 - invoke-static {v$identifierRegister}, $builderMethodDescriptor - move-result-object v0 - iget-object v0, v0, $emptyComponentFieldDescriptor - return-object v0 - """, listOf(ExternalLabel("not_an_ad", method.instruction(insertIndex))) + addInstructions( + insertIndex, """ + invoke-static {v$stringBuilderRegister, v$identifierRegister}, $MUSIC_ADS_PATH/MusicLithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z + move-result v$bufferRegister + if-eqz v$bufferRegister, :not_an_ad + move-object/from16 v$identifierRegister, p1 + invoke-static {v$identifierRegister}, $builderMethodDescriptor + move-result-object v0 + iget-object v0, v0, $emptyComponentFieldDescriptor + return-object v0 + """, listOf(ExternalLabel("not_an_ad", instruction(insertIndex))) ) } } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt index b94e3db70..cbe120b03 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt @@ -19,9 +19,7 @@ import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility @YouTubeMusicCompatibility @Version("0.0.1") class MinimizedPlaybackPatch : BytecodePatch( - listOf( - MinimizedPlaybackManagerFingerprint - ) + listOf(MinimizedPlaybackManagerFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { diff --git a/src/main/kotlin/app/revanced/patches/music/misc/premium/fingerprints/AccountMenuFooterFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/premium/fingerprints/AccountMenuFooterFingerprint.kt new file mode 100644 index 000000000..c09386624 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/premium/fingerprints/AccountMenuFooterFingerprint.kt @@ -0,0 +1,22 @@ +package app.revanced.patches.music.misc.premium.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.privacyTosFooterId +import app.revanced.util.bytecode.isWideLiteralExists +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +object AccountMenuFooterFingerprint : MethodFingerprint( + returnType = "L", + access = AccessFlags.PUBLIC or AccessFlags.FINAL, + opcodes = listOf( + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT + ), + customFingerprint = { it.isWideLiteralExists(privacyTosFooterId) } +) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/premium/patch/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/premium/patch/HideGetPremiumPatch.kt index e60981deb..8f4f4acee 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/premium/patch/HideGetPremiumPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/premium/patch/HideGetPremiumPatch.kt @@ -1,6 +1,5 @@ package app.revanced.patches.music.misc.premium.patch -import app.revanced.extensions.findMutableMethodOf import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name @@ -8,48 +7,43 @@ import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.toMethodWalker import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.extensions.instruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.DependsOn import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.music.misc.premium.fingerprints.AccountMenuFooterFingerprint import app.revanced.patches.music.misc.premium.fingerprints.HideGetPremiumFingerprint +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.privacyTosFooterId import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility -import app.revanced.patches.shared.patch.mapping.ResourceMappingPatch +import app.revanced.util.bytecode.getWideLiteralIndex import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.instruction.formats.Instruction31i -import org.jf.dexlib2.iface.reference.FieldReference +import org.jf.dexlib2.iface.reference.Reference @Patch @Name("hide-get-premium") @Description("Removes all \"Get Premium\" evidences from the avatar menu.") -@DependsOn([ResourceMappingPatch::class]) +@DependsOn([SharedResourceIdPatch::class]) @YouTubeMusicCompatibility @Version("0.0.1") class HideGetPremiumPatch : BytecodePatch( listOf( + AccountMenuFooterFingerprint, HideGetPremiumFingerprint ) ) { - // list of resource names to get the id of - private val resourceIds = arrayOf( - "id" to "privacy_tos_footer" - ).map { (type, name) -> - ResourceMappingPatch - .resourceMappings - .single { it.type == type && it.name == name }.id - } - override fun execute(context: BytecodeContext): PatchResult { HideGetPremiumFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val insertIndex = it.scanResult.patternScanResult!!.startIndex - val register = (implementation!!.instructions[insertIndex] as TwoRegisterInstruction).registerA + val register = instruction(insertIndex).registerA addInstruction( insertIndex + 1, @@ -58,54 +52,40 @@ class HideGetPremiumPatch : BytecodePatch( } } ?: return HideGetPremiumFingerprint.toErrorResult() - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - with(method.implementation) { - this?.instructions?.forEachIndexed { index, instruction -> - when (instruction.opcode) { - Opcode.CONST -> { - when ((instruction as Instruction31i).wideLiteral) { - resourceIds[0] -> { - val viewIndex = index + 5 - val viewInstruction = instructions.elementAt(viewIndex) - if (viewInstruction.opcode != Opcode.IGET_OBJECT) return@forEachIndexed - val mutableMethod = context.proxy(classDef).mutableClass.findMutableMethodOf(method) + AccountMenuFooterFingerprint.result?.let { + it.mutableMethod.apply { + val targetIndex = getWideLiteralIndex(privacyTosFooterId) + 4 + targetReference = instruction(targetIndex + 1).reference - val viewReference = (viewInstruction as? ReferenceInstruction)?.reference as? FieldReference + with (context + .toMethodWalker(this) + .nextMethod(targetIndex, true) + .getMethod() as MutableMethod + ) { + this.implementation!!.instructions.apply { + for ((index, instruction) in withIndex()) { + if (instruction.opcode != Opcode.IGET_OBJECT) continue - with (context - .toMethodWalker(mutableMethod) - .nextMethod(viewIndex - 1, true) - .getMethod() as MutableMethod - ) { - val viewInstructions = implementation!!.instructions + if (instruction(index).reference == targetReference) { + val targetRegister = instruction(index + 2).registerA - for ((targetIndex, targetInstruction) in viewInstructions.withIndex()) { - if (targetInstruction.opcode != Opcode.IGET_OBJECT) continue + addInstruction( + index, + "const/16 v$targetRegister, 0x8" + ) - val indexReference = (targetInstruction as ReferenceInstruction).reference as FieldReference - - if (indexReference == viewReference) { - val targetRegister = (viewInstructions.elementAt(targetIndex + 2) as OneRegisterInstruction).registerA - addInstruction( - targetIndex, - "const/16 v$targetRegister, 0x8" - ) - break - } - } - } - } - } + break } - else -> return@forEachIndexed } } } } - } + } ?: return AccountMenuFooterFingerprint.toErrorResult() return PatchResultSuccess() } + private companion object{ + lateinit var targetReference: Reference + } } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySetterParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySetterParentFingerprint.kt index 73663213e..9676b69fb 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySetterParentFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySetterParentFingerprint.kt @@ -1,17 +1,11 @@ package app.revanced.patches.music.misc.quality.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.qualityAutoId +import app.revanced.util.bytecode.isWideLiteralExists object MusicVideoQualitySetterParentFingerprint : MethodFingerprint( returnType = "V", parameters = listOf("L"), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.qualityAutoLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(qualityAutoId)} ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySettingsParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySettingsParentFingerprint.kt index 8dd0a771d..1b8cde28e 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySettingsParentFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/quality/fingerprints/MusicVideoQualitySettingsParentFingerprint.kt @@ -1,17 +1,11 @@ package app.revanced.patches.music.misc.quality.fingerprints import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.qualityTitleId +import app.revanced.util.bytecode.isWideLiteralExists object MusicVideoQualitySettingsParentFingerprint : MethodFingerprint( returnType = "L", parameters = listOf(), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.qualityTitleLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(qualityTitleId)} ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/quality/patch/VideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/quality/patch/VideoQualityPatch.kt index cb6dab123..ba8be9ff1 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/quality/patch/VideoQualityPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/quality/patch/VideoQualityPatch.kt @@ -25,6 +25,7 @@ import app.revanced.util.integrations.Constants.MUSIC_MISC_PATH import org.jf.dexlib2.builder.instruction.BuilderInstruction21c import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.reference.FieldReference +import org.jf.dexlib2.iface.reference.Reference @Patch @Name("remember-video-quality") @@ -48,46 +49,48 @@ class VideoQualityPatch : BytecodePatch( override fun execute(context: BytecodeContext): PatchResult { MusicVideoQualitySetterParentFingerprint.result?.let { parentResult -> - MusicVideoQualitySetterFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { result -> - val endIndex = result.scanResult.patternScanResult!!.endIndex - val instructions = result.method.implementation!!.instructions + MusicVideoQualitySetterFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex - qualityFieldReference = - (instructions.elementAt(endIndex) as ReferenceInstruction).reference as FieldReference + qualityReference = instruction(endIndex).reference + qualityFieldReference = qualityReference as FieldReference - qIndexMethodName = - context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name + qIndexMethodName = context + .classes.single { classDef -> classDef.type == qualityFieldReference.type } + .methods.single { method -> method.parameterTypes.first() == "I" }.name + } } ?: return MusicVideoQualitySetterFingerprint.toErrorResult() } ?: return MusicVideoQualitySetterParentFingerprint.toErrorResult() MusicVideoQualitySettingsParentFingerprint.result?.let { parentResult -> - MusicVideoQualitySettingsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.let { - it.mutableMethod.addInstructions( - 0, """ - const-string v0, "$qIndexMethodName" - sput-object v0, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->qIndexMethod:Ljava/lang/String; - iget-object v0, p0, ${it.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type} - invoke-static {p1, p2, v0}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;)I - move-result p2 - """ - ) - } ?: return MusicVideoQualitySettingsFingerprint.toErrorResult() + MusicVideoQualitySettingsFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstructions( + 0, """ + const-string v0, "$qIndexMethodName" + sput-object v0, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->qIndexMethod:Ljava/lang/String; + iget-object v0, p0, $qualityReference + invoke-static {p1, p2, v0}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;)I + move-result p2 + """ + ) ?: return MusicVideoQualitySettingsFingerprint.toErrorResult() } ?: return MusicVideoQualitySettingsParentFingerprint.toErrorResult() UserQualityChangeFingerprint.result?.let { - val endIndex = it.scanResult.patternScanResult!!.endIndex - val qualityChangedClass = - context.findClass((it.mutableMethod.instruction(endIndex) as BuilderInstruction21c) - .reference.toString())!! - .mutableClass + it.mutableMethod.apply { + val endIndex = it.scanResult.patternScanResult!!.endIndex + val qualityChangedClass = + context.findClass((instruction(endIndex)) + .reference.toString())!! + .mutableClass - for (method in qualityChangedClass.methods) { - with (qualityChangedClass.findMutableMethodOf(method)) { - if (this.name == "onItemClick") { - addInstruction( - 0, - "invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V" - ) + for (method in qualityChangedClass.methods) { + with (qualityChangedClass.findMutableMethodOf(method)) { + if (this.name == "onItemClick") { + addInstruction( + 0, + "invoke-static {p3}, $INTEGRATIONS_VIDEO_QUALITY_CLASS_DESCRIPTOR->userChangedQuality(I)V" + ) + } } } } @@ -104,6 +107,6 @@ class VideoQualityPatch : BytecodePatch( private lateinit var qIndexMethodName: String private lateinit var qualityFieldReference: FieldReference - + private lateinit var qualityReference: Reference } } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt index bfe2672e4..d864b579e 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/resourceid/patch/SharedResourceIdPatch.kt @@ -18,13 +18,15 @@ import app.revanced.util.enum.ResourceType.* @Version("0.0.1") class SharedResourceIdPatch : ResourcePatch { internal companion object { - var colorGreyLabelId: Long = -1 - var dialogSolidLabelId: Long = -1 - var disabledIconLabelId: Long = -1 - var isTabletLabelId: Long = -1 - var notifierShelfLabelId: Long = -1 - var qualityAutoLabelId: Long = -1 - var qualityTitleLabelId: Long = -1 + var chipCloudId: Long = -1 + var colorGreyId: Long = -1 + var dialogSolidId: Long = -1 + var disabledIconId: Long = -1 + var isTabletId: Long = -1 + var notifierShelfId: Long = -1 + var privacyTosFooterId: Long = -1 + var qualityAutoId: Long = -1 + var qualityTitleId: Long = -1 } override fun execute(context: ResourceContext): PatchResult { @@ -33,13 +35,15 @@ class SharedResourceIdPatch : ResourcePatch { .resourceMappings .single { it.type == type.value && it.name == name }.id - colorGreyLabelId = find(COLOR, "ytm_color_grey_12") - dialogSolidLabelId = find(STYLE, "Theme.YouTubeMusic.Dialog.Solid") - disabledIconLabelId = find(DIMEN, "disabled_icon_alpha") - isTabletLabelId = find(BOOL, "is_tablet") - notifierShelfLabelId = find(LAYOUT, "music_notifier_shelf") - qualityAutoLabelId = find(STRING, "quality_auto") - qualityTitleLabelId = find(STRING, "quality_title") + chipCloudId = find(LAYOUT, "chip_cloud") + colorGreyId = find(COLOR, "ytm_color_grey_12") + dialogSolidId = find(STYLE, "Theme.YouTubeMusic.Dialog.Solid") + disabledIconId = find(DIMEN, "disabled_icon_alpha") + isTabletId = find(BOOL, "is_tablet") + notifierShelfId = find(LAYOUT, "music_notifier_shelf") + privacyTosFooterId = find(ID, "privacy_tos_footer") + qualityAutoId = find(STRING, "quality_auto") + qualityTitleId = find(STRING, "quality_title") return PatchResultSuccess() } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/settings/bytecode/patch/MusicSettingsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/settings/bytecode/patch/MusicSettingsBytecodePatch.kt index 2c1ca2dad..16743cf7e 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/settings/bytecode/patch/MusicSettingsBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/settings/bytecode/patch/MusicSettingsBytecodePatch.kt @@ -30,9 +30,10 @@ class MusicSettingsBytecodePatch : BytecodePatch( override fun execute(context: BytecodeContext): PatchResult { SettingsHeadersFragmentFingerprint.result?.let { - with(it.mutableMethod) { + it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.endIndex - val targetRegister = (instruction(targetIndex) as OneRegisterInstruction).registerA + val targetRegister = instruction(targetIndex).registerA + addInstruction( targetIndex + 1, "invoke-static {v$targetRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->setActivity(Ljava/lang/Object;)V" @@ -41,10 +42,11 @@ class MusicSettingsBytecodePatch : BytecodePatch( } ?: return SettingsHeadersFragmentFingerprint.toErrorResult() PreferenceFingerprint.result?.let { - with(it.mutableMethod) { + it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.endIndex - val keyRegister = (instruction(targetIndex) as FiveRegisterInstruction).registerD - val valueRegister = (instruction(targetIndex) as FiveRegisterInstruction).registerE + val keyRegister = instruction(targetIndex).registerD + val valueRegister = instruction(targetIndex).registerE + addInstruction( targetIndex, "invoke-static {v$keyRegister, v$valueRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onPreferenceChanged(Ljava/lang/String;Z)V" diff --git a/src/main/kotlin/app/revanced/patches/music/misc/settings/resource/patch/MusicSettingsPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/settings/resource/patch/MusicSettingsPatch.kt index 0ee0ed1fd..7c402ebe7 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/settings/resource/patch/MusicSettingsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/settings/resource/patch/MusicSettingsPatch.kt @@ -44,7 +44,6 @@ class MusicSettingsPatch : AbstractSettingsResourcePatch( /** * Copy colors */ - context.xmlEditor["res/values/colors.xml"].use { editor -> val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sharebuttonhook/patch/ShareButtonHookPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/sharebuttonhook/patch/ShareButtonHookPatch.kt index b71bcf0ef..35a34c047 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/sharebuttonhook/patch/ShareButtonHookPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/sharebuttonhook/patch/ShareButtonHookPatch.kt @@ -45,7 +45,7 @@ class ShareButtonHookPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext): PatchResult { SharePanelFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.startIndex addInstructions( diff --git a/src/main/kotlin/app/revanced/patches/music/misc/shuffle/fingerprints/ShuffleClassFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/shuffle/fingerprints/ShuffleClassFingerprint.kt index 2b7404528..aa0b275bb 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/shuffle/fingerprints/ShuffleClassFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/shuffle/fingerprints/ShuffleClassFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.music.misc.shuffle.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.disabledIconId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -18,12 +18,6 @@ object ShuffleClassFingerprint : MethodFingerprint( Opcode.INVOKE_VIRTUAL, Opcode.RETURN_VOID ), - customFingerprint = { methodDef -> - methodDef.name == "" && - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.disabledIconLabelId - } == true - } + customFingerprint = { it.name == "" && it.isWideLiteralExists(disabledIconId) } ) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/shuffle/patch/EnforceShufflePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/shuffle/patch/EnforceShufflePatch.kt index 89817ac6f..ad7d8528b 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/shuffle/patch/EnforceShufflePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/shuffle/patch/EnforceShufflePatch.kt @@ -6,7 +6,10 @@ import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.* +import app.revanced.patcher.extensions.addInstruction +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction +import app.revanced.patcher.extensions.or import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess @@ -23,9 +26,10 @@ import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.util.enum.CategoryType import app.revanced.util.integrations.Constants.MUSIC_MISC_PATH import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference +import org.jf.dexlib2.iface.instruction.Instruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.reference.FieldReference +import org.jf.dexlib2.iface.reference.Reference import org.jf.dexlib2.immutable.ImmutableField import org.jf.dexlib2.immutable.ImmutableMethod import org.jf.dexlib2.immutable.ImmutableMethodImplementation @@ -51,31 +55,31 @@ class EnforceShufflePatch : BytecodePatch( ) { override fun execute(context: BytecodeContext): PatchResult { - ShuffleClassReferenceFingerprint.result?.let { result -> - val startIndex = result.scanResult.patternScanResult!!.startIndex - val endIndex = result.scanResult.patternScanResult!!.endIndex - SHUFFLE_CLASS = result.classDef.type - - with (result.mutableMethod.implementation!!.instructions) { - firstRef = (elementAt(startIndex) as ReferenceInstruction).reference as FieldReference - secondRef = (elementAt(startIndex + 1) as ReferenceInstruction).reference as DexBackedMethodReference - thirdRef = (elementAt(endIndex) as ReferenceInstruction).reference as FieldReference - - this.filter { instruction -> - val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference - fieldReference?.let { it.type == "Landroid/widget/ImageView;" } == true - }.forEach { instruction -> - fourthRef = (instruction as ReferenceInstruction).reference as FieldReference + ShuffleClassReferenceFingerprint.result?.let { + it.mutableMethod.apply { + val startIndex = it.scanResult.patternScanResult!!.startIndex + val endIndex = it.scanResult.patternScanResult!!.endIndex + val imageViewIndex = implementation!!.instructions.indexOfFirst { instruction -> + ((instruction as? ReferenceInstruction)?.reference as? FieldReference)?.type == "Landroid/widget/ImageView;" } + + SHUFFLE_CLASS = it.classDef.type + + shuffleReference1 = instruction(startIndex).descriptor + shuffleReference2 = instruction(startIndex + 1).descriptor + shuffleReference3 = instruction(endIndex).descriptor + shuffleReference4 = instruction(imageViewIndex).descriptor } } ?: return ShuffleClassReferenceFingerprint.toErrorResult() ShuffleClassFingerprint.result?.let { - it.mutableMethod.addInstruction( - it.scanResult.patternScanResult!!.endIndex, - "sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleclass:$SHUFFLE_CLASS" - ) + it.mutableMethod.apply { + addInstruction( + it.scanResult.patternScanResult!!.endIndex, + "sput-object p0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleclass:$SHUFFLE_CLASS" + ) + } context.traverseClassHierarchy(it.mutableClass) { accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL @@ -93,68 +97,70 @@ class EnforceShufflePatch : BytecodePatch( } } ?: return ShuffleClassFingerprint.toErrorResult() - MusicPlaybackControlsFingerprint.result?.let { - with (it.mutableMethod.implementation!!.instructions) { - fifthRef = (elementAt(0) as ReferenceInstruction).reference as FieldReference - sixthRef = (elementAt(1) as ReferenceInstruction).reference as DexBackedMethodReference + it.mutableMethod.apply { + shuffleReference5 = instruction(0).descriptor + shuffleReference6 = instruction(1).descriptor + + addInstructions( + 0, """ + invoke-virtual {v0, v1}, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->buttonHook(Z)V + return-void + """ + ) } - it.mutableClass.staticFields.add( - ImmutableField( - it.mutableMethod.definingClass, - "shuffleclass", - SHUFFLE_CLASS, - AccessFlags.PUBLIC or AccessFlags.STATIC, - null, - null, - null - ).toMutable() - ) + it.mutableClass.apply { + staticFields.add( + ImmutableField( + it.mutableMethod.definingClass, + "shuffleclass", + SHUFFLE_CLASS, + AccessFlags.PUBLIC or AccessFlags.STATIC, + null, + null, + null + ).toMutable() + ) - it.mutableMethod.addInstructions( - 0, - """ - invoke-virtual {v0, v1}, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->buttonHook(Z)V - return-void - """ - ) + val shuffleFieldReference = shuffleReference3 as FieldReference - it.mutableClass.methods.add( - ImmutableMethod( - it.classDef.type, - "buttonHook", - listOf(ImmutableMethodParameter("Z", null, null)), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - null, - null, - ImmutableMethodImplementation( - 5, """ + methods.add( + ImmutableMethod( + it.classDef.type, + "buttonHook", + listOf(ImmutableMethodParameter("Z", null, null)), + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + null, + null, + ImmutableMethodImplementation( + 5, """ invoke-static {}, $MUSIC_MISC_PATH/ForceShufflePatch;->enableForceShuffle()Z move-result v0 if-eqz v0, :cond_0 new-instance v0, $SHUFFLE_CLASS sget-object v0, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->shuffleclass:$SHUFFLE_CLASS - iget-object v1, v0, $SHUFFLE_CLASS->${firstRef.name}:${firstRef.type} - invoke-interface {v1}, $secondRef + iget-object v1, v0, $shuffleReference1 + invoke-interface {v1}, $shuffleReference2 move-result-object v1 - check-cast v1, ${thirdRef.definingClass} - iget-object v1, v1, ${thirdRef.definingClass}->${thirdRef.name}:${thirdRef.type} - invoke-virtual {v1}, ${thirdRef.type}->ordinal()I + check-cast v1, ${shuffleFieldReference.definingClass} + iget-object v1, v1, $shuffleReference3 + invoke-virtual {v1}, ${shuffleFieldReference.type}->ordinal()I move-result v1 - iget-object v2, v0, $SHUFFLE_CLASS->${fourthRef.name}:Landroid/widget/ImageView; + iget-object v2, v0, $shuffleReference4 invoke-virtual {v2}, Landroid/widget/ImageView;->performClick()Z if-eqz v1, :cond_0 invoke-virtual {v2}, Landroid/widget/ImageView;->performClick()Z :cond_0 - iput-boolean v4, v3, $MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR->${fifthRef.name}:${fifthRef.type} - invoke-virtual {v3}, $sixthRef + iput-boolean v4, v3, $shuffleReference5 + invoke-virtual {v3}, $shuffleReference6 return-void """.toInstructions(), null, null - ) - ).toMutable() - ) + ) + ).toMutable() + ) + } } ?: return MusicPlaybackControlsFingerprint.toErrorResult() MusicSettingsPatch.addMusicPreference(CategoryType.MISC, "revanced_enable_force_shuffle", "true") @@ -162,18 +168,19 @@ class EnforceShufflePatch : BytecodePatch( return PatchResultSuccess() } - companion object { + private companion object { const val MUSIC_PLAYBACK_CONTROLS_CLASS_DESCRIPTOR = "Lcom/google/android/apps/youtube/music/watchpage/MusicPlaybackControls;" - private lateinit var SHUFFLE_CLASS: String + lateinit var SHUFFLE_CLASS: String + lateinit var shuffleReference1: Reference + lateinit var shuffleReference2: Reference + lateinit var shuffleReference3: Reference + lateinit var shuffleReference4: Reference + lateinit var shuffleReference5: Reference + lateinit var shuffleReference6: Reference - private lateinit var firstRef: FieldReference - private lateinit var secondRef: DexBackedMethodReference - private lateinit var thirdRef: FieldReference - private lateinit var fourthRef: FieldReference - - private lateinit var fifthRef: FieldReference - private lateinit var sixthRef: DexBackedMethodReference + val Instruction.descriptor + get() = (this as ReferenceInstruction).reference } } diff --git a/src/main/kotlin/app/revanced/patches/music/misc/tastebuilder/patch/RemoveTasteBuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/tastebuilder/patch/RemoveTasteBuilderPatch.kt index 899fb7efb..3a57d2752 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/tastebuilder/patch/RemoveTasteBuilderPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/tastebuilder/patch/RemoveTasteBuilderPatch.kt @@ -6,13 +6,14 @@ import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.instruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.annotations.Patch import app.revanced.patches.music.misc.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility -import org.jf.dexlib2.iface.instruction.formats.Instruction22c +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction @Patch @Name("hide-taste-builder") @@ -20,15 +21,13 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction22c @YouTubeMusicCompatibility @Version("0.0.1") class RemoveTasteBuilderPatch : BytecodePatch( - listOf( - TasteBuilderConstructorFingerprint - ) + listOf(TasteBuilderConstructorFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { TasteBuilderConstructorFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val insertIndex = it.scanResult.patternScanResult!!.endIndex - 8 - val register = (implementation!!.instructions[insertIndex] as Instruction22c).registerA + val register = instruction(insertIndex).registerA addInstructions( insertIndex, """ diff --git a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/NotifierShelfFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/NotifierShelfFingerprint.kt index 07ec13974..666e4945a 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/NotifierShelfFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/NotifierShelfFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.music.misc.upgradebutton.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch.Companion.notifierShelfId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -16,11 +16,6 @@ object NotifierShelfFingerprint : MethodFingerprint( Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT_OBJECT ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.notifierShelfLabelId - } == true - } + customFingerprint = { it.isWideLiteralExists(notifierShelfId)} ) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt index 8e6f8c2e8..ac6081edb 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt @@ -2,9 +2,9 @@ package app.revanced.patches.music.misc.upgradebutton.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import app.revanced.util.bytecode.isNarrowLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction object PivotBarConstructorFingerprint : MethodFingerprint( returnType = "V", @@ -13,10 +13,5 @@ object PivotBarConstructorFingerprint : MethodFingerprint( Opcode.IPUT_OBJECT, Opcode.RETURN_VOID ), - customFingerprint = { methodDef -> - methodDef.name == "" - && methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 117501096) - } - } + customFingerprint = { it.name == "" && it.isNarrowLiteralExists(117501096) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/patch/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/patch/RemoveUpgradeButtonPatch.kt index 75c290d42..5879b9f42 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/patch/RemoveUpgradeButtonPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/upgradebutton/patch/RemoveUpgradeButtonPatch.kt @@ -22,7 +22,6 @@ import app.revanced.util.integrations.Constants.INTEGRATIONS_PATH import org.jf.dexlib2.iface.instruction.OneRegisterInstruction import org.jf.dexlib2.iface.instruction.ReferenceInstruction import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.reference.FieldReference @Patch @Name("hide-upgrade-button") @@ -43,20 +42,12 @@ class RemoveUpgradeButtonPatch : BytecodePatch( ) { override fun execute(context: BytecodeContext): PatchResult { PivotBarConstructorFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.startIndex + val targetRegisterA = instruction(targetIndex).registerA + val targetRegisterB = instruction(targetIndex).registerB - val targetRegisterA = (instruction(targetIndex) as TwoRegisterInstruction).registerA - val targetRegisterB = (instruction(targetIndex) as TwoRegisterInstruction).registerB - - val replaceReference = - (instruction(targetIndex) as ReferenceInstruction).reference as FieldReference - - val replaceReferenceToCall = replaceReference.definingClass + - "->" + - replaceReference.name + - ":" + - replaceReference.type + val replaceReference = instruction(targetIndex).reference.toString() replaceInstruction( targetIndex, @@ -69,16 +60,16 @@ class RemoveUpgradeButtonPatch : BytecodePatch( if-le v1, v2, :dismiss invoke-interface {v$targetRegisterA, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; :dismiss - iput-object v$targetRegisterA, v$targetRegisterB, $replaceReferenceToCall + iput-object v$targetRegisterA, v$targetRegisterB, $replaceReference """ ) } } ?: return PivotBarConstructorFingerprint.toErrorResult() NotifierShelfFingerprint.result?.let { - with (it.mutableMethod) { + it.mutableMethod.apply { val targetIndex = it.scanResult.patternScanResult!!.endIndex - val targetRegister = (instruction(targetIndex) as OneRegisterInstruction).registerA + val targetRegister = instruction(targetIndex).registerA addInstruction( targetIndex + 1, "invoke-static {v$targetRegister}, $INTEGRATIONS_PATH/adremover/AdRemoverAPI;->HideViewWithLayout1dp(Landroid/view/View;)V" diff --git a/src/main/kotlin/app/revanced/patches/music/misc/videoid/patch/MusicVideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/videoid/patch/MusicVideoIdPatch.kt index a10143869..b7e69d74a 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/videoid/patch/MusicVideoIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/videoid/patch/MusicVideoIdPatch.kt @@ -20,18 +20,15 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction @YouTubeMusicCompatibility @Version("0.0.1") class MusicVideoIdPatch : BytecodePatch( - listOf( - MusicVideoIdFingerprint - ) + listOf(MusicVideoIdFingerprint) ) { override fun execute(context: BytecodeContext): PatchResult { MusicVideoIdFingerprint.result?.let { - insertIndex = it.scanResult.patternScanResult!!.endIndex - - with (it.mutableMethod) { + it.mutableMethod.apply { + insertIndex = it.scanResult.patternScanResult!!.endIndex insertMethod = this - videoIdRegister = (implementation!!.instructions[insertIndex] as OneRegisterInstruction).registerA + videoIdRegister = instruction(insertIndex).registerA } offset++ // offset so setVideoId is called before any injected call } ?: return MusicVideoIdFingerprint.toErrorResult() diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/MiniplayerColorParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/ColorMatchPlayerParentFingerprint.kt similarity index 91% rename from src/main/kotlin/app/revanced/patches/shared/fingerprints/MiniplayerColorParentFingerprint.kt rename to src/main/kotlin/app/revanced/patches/shared/fingerprints/ColorMatchPlayerParentFingerprint.kt index 129ef1383..eaa4c75a3 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/MiniplayerColorParentFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/ColorMatchPlayerParentFingerprint.kt @@ -5,7 +5,7 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode -object MiniplayerColorParentFingerprint : MethodFingerprint( +object ColorMatchPlayerParentFingerprint : MethodFingerprint( returnType = "V", access = AccessFlags.PRIVATE or AccessFlags.FINAL, opcodes = listOf( diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/LayoutConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LayoutConstructorFingerprint.kt index 6514ad2d4..ff8eef19e 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/LayoutConstructorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/LayoutConstructorFingerprint.kt @@ -4,7 +4,5 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint object LayoutConstructorFingerprint : MethodFingerprint( strings = listOf("1.0x"), - customFingerprint = { - it.definingClass.endsWith("YouTubeControlsOverlay;") - } + customFingerprint = { it.definingClass.endsWith("YouTubeControlsOverlay;") } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt index 202e68781..115ab32d3 100644 --- a/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/shared/fingerprints/PivotBarCreateButtonViewFingerprint.kt @@ -2,8 +2,8 @@ package app.revanced.patches.shared.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction +import app.revanced.patches.youtube.misc.resourceid.patch.SharedResourceIdPatch.Companion.imageOnlyTabId +import app.revanced.util.bytecode.isWideLiteralExists import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.Opcode @@ -14,10 +14,5 @@ object PivotBarCreateButtonViewFingerprint : MethodFingerprint( Opcode.MOVE_OBJECT, Opcode.INVOKE_DIRECT_RANGE, // unique instruction anchor ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && - (it as? WideLiteralInstruction)?.wideLiteral == SharedResourceIdPatch.imageOnlyTabId - } == true - } + customFingerprint = { it.isWideLiteralExists(imageOnlyTabId) } ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/bytecode/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/bytecode/BytecodeUtils.kt new file mode 100644 index 000000000..ad83166e0 --- /dev/null +++ b/src/main/kotlin/app/revanced/util/bytecode/BytecodeUtils.kt @@ -0,0 +1,30 @@ +package app.revanced.util.bytecode + +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction + +fun Method.getNarrowLiteralIndex(value: Int): Int { + return implementation?.let { + it.instructions.indexOfFirst { instruction -> + instruction.opcode == Opcode.CONST && (instruction as NarrowLiteralInstruction).narrowLiteral == value + } + } ?: -1 +} + +fun Method.isNarrowLiteralExists(value: Int): Boolean { + return getNarrowLiteralIndex(value) != -1 +} + +fun Method.getWideLiteralIndex(value: Long): Int { + return implementation?.let { + it.instructions.indexOfFirst { instruction -> + instruction.opcode == Opcode.CONST && (instruction as WideLiteralInstruction).wideLiteral == value + } + } ?: -1 +} + +fun Method.isWideLiteralExists(value: Long): Boolean { + return getWideLiteralIndex(value) != -1 +}