From 22498750e7b8835eba8882a3c9b52d8fa31995f7 Mon Sep 17 00:00:00 2001 From: inotia00 Date: Fri, 28 Apr 2023 11:32:16 +0900 Subject: [PATCH] add `sleep-timer-hook` patch (included in `share-button-hook` patch) --- .../patch/MusicMicroGResourcePatch.kt | 4 + .../patch/ShareButtonHookPatch.kt | 4 +- .../MusicPlaybackControlsClickFingerprint.kt | 13 +++ .../MusicPlaybackControlsTimeFingerprint.kt | 13 +++ .../SleepTimerFinalFingerprint.kt | 9 ++ .../SleepTimerStaticFingerprint.kt | 9 ++ .../patch/SleepTimerHookPatch.kt | 110 ++++++++++++++++++ 7 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsClickFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsTimeFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerFinalFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerStaticFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/patch/SleepTimerHookPatch.kt diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/resource/patch/MusicMicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/resource/patch/MusicMicroGResourcePatch.kt index 8eff0fb9d..fb03f86fb 100644 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/resource/patch/MusicMicroGResourcePatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/misc/microg/resource/patch/MusicMicroGResourcePatch.kt @@ -15,6 +15,7 @@ import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.patches.shared.patch.options.PatchOptions import app.revanced.util.microg.MicroGManifestHelper.addSpoofingMetadata import app.revanced.util.microg.MicroGResourceHelper.patchManifest +import app.revanced.util.resources.MusicResourceHelper.setMicroG @Name("music-microg-resource-patch") @Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.") @@ -40,6 +41,9 @@ class MusicMicroGResourcePatch : ResourcePatch { SPOOFED_PACKAGE_NAME, SPOOFED_PACKAGE_SIGNATURE ) + + context.setMicroG(packageNameMusic) + return PatchResultSuccess() } } \ No newline at end of file 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 b9b4ed4df..b71bcf0ef 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 @@ -16,6 +16,7 @@ import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patches.music.misc.settings.resource.patch.MusicSettingsPatch import app.revanced.patches.music.misc.sharebuttonhook.fingerprints.* +import app.revanced.patches.music.misc.sleeptimerhook.patch.SleepTimerHookPatch import app.revanced.patches.music.misc.videoid.patch.MusicVideoIdPatch import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility import app.revanced.util.enum.CategoryType @@ -28,7 +29,8 @@ import app.revanced.util.integrations.Constants.MUSIC_MISC_PATH @DependsOn( [ MusicSettingsPatch::class, - MusicVideoIdPatch::class + MusicVideoIdPatch::class, + SleepTimerHookPatch::class ] ) @YouTubeMusicCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsClickFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsClickFingerprint.kt new file mode 100644 index 000000000..7aabda66e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsClickFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.music.misc.sleeptimerhook.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint +import org.jf.dexlib2.Opcode + +object MusicPlaybackControlsClickFingerprint : MethodFingerprint( + returnType = "V", + opcodes = listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.RETURN_VOID + ), + customFingerprint = { it.definingClass.endsWith("/MusicPlaybackControls;") && it.name == "onClick" } +) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsTimeFingerprint.kt new file mode 100644 index 000000000..aeb3738aa --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/MusicPlaybackControlsTimeFingerprint.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.music.misc.sleeptimerhook.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 MusicPlaybackControlsTimeFingerprint : MethodFingerprint( + returnType = "V", + access = AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.SYNTHETIC, + parameters = listOf("J","J","J","J"), + opcodes = listOf(Opcode.RETURN_VOID), +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerFinalFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerFinalFingerprint.kt new file mode 100644 index 000000000..8403ae5ad --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerFinalFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.music.misc.sleeptimerhook.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint + +object SleepTimerFinalFingerprint : MethodFingerprint( + returnType = "V", + parameters = listOf("L"), + strings = listOf("SLEEP_TIMER_MENU_BOTTOM_SHEET_FRAGMENT") +) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerStaticFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerStaticFingerprint.kt new file mode 100644 index 000000000..62d00dbab --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/fingerprints/SleepTimerStaticFingerprint.kt @@ -0,0 +1,9 @@ +package app.revanced.patches.music.misc.sleeptimerhook.fingerprints + +import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint + +object SleepTimerStaticFingerprint : MethodFingerprint( + returnType = "L", + parameters = listOf("L"), + strings = listOf("SLEEP_TIMER_MENU_BOTTOM_SHEET_FRAGMENT") +) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/patch/SleepTimerHookPatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/patch/SleepTimerHookPatch.kt new file mode 100644 index 000000000..99fa07db8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/misc/sleeptimerhook/patch/SleepTimerHookPatch.kt @@ -0,0 +1,110 @@ +package app.revanced.patches.music.misc.sleeptimerhook.patch + +import app.revanced.extensions.toErrorResult +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.or +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.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.music.misc.sleeptimerhook.fingerprints.* +import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility +import app.revanced.util.integrations.Constants.MUSIC_MISC_PATH +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference +import org.jf.dexlib2.iface.instruction.ReferenceInstruction +import org.jf.dexlib2.immutable.ImmutableMethod +import org.jf.dexlib2.immutable.ImmutableMethodImplementation + +@Name("sleep-timer-hook") +@YouTubeMusicCompatibility +@Version("0.0.1") +class SleepTimerHookPatch : BytecodePatch( + listOf( + MusicPlaybackControlsClickFingerprint, + SleepTimerFinalFingerprint, + SleepTimerStaticFingerprint + ) +) { + override fun execute(context: BytecodeContext): PatchResult { + val sleepTimerStaticMethod = SleepTimerStaticFingerprint.result?.mutableMethod + ?: return SleepTimerStaticFingerprint.toErrorResult() + + val sleepTimerStaticMethodToCall = sleepTimerStaticMethod.definingClass + + "->" + + sleepTimerStaticMethod.name + + "(${sleepTimerStaticMethod.parameters[0]})" + + sleepTimerStaticMethod.returnType + + + val sleepTimerFinalMethod = SleepTimerFinalFingerprint.result?.mutableMethod + ?: return SleepTimerFinalFingerprint.toErrorResult() + + val sleepTimerFinalMethodToCall = sleepTimerFinalMethod.definingClass + + "->" + + sleepTimerFinalMethod.name + + "(${sleepTimerFinalMethod.parameters[0]})" + + sleepTimerFinalMethod.returnType + + + MusicPlaybackControlsClickFingerprint.result?.let { parentResult -> + with (parentResult.mutableMethod.implementation!!.instructions) { + for (i in this.size - 1 downTo 0) { + if (this[i].opcode != Opcode.IGET_OBJECT) continue + + val invokeInstruction = this[i] as? ReferenceInstruction ?: continue + val targetReference = (invokeInstruction.reference as DexBackedFieldReference).toString() + if (!targetReference.contains(parentResult.classDef.type)) continue + musicPlaybackControlsMethodToCall = targetReference + break + } + if (musicPlaybackControlsMethodToCall == null) + return MusicPlaybackControlsClickFingerprint.toErrorResult() + } + + MusicPlaybackControlsTimeFingerprint.also { it.resolve(context, parentResult.classDef) }.result?.mutableMethod?.addInstruction( + 1, + "invoke-virtual {p0}, ${parentResult.classDef.type}->openSleepTimer()V" + ) ?: return MusicPlaybackControlsTimeFingerprint.toErrorResult() + + parentResult.mutableClass.methods.add( + ImmutableMethod( + parentResult.classDef.type, + "openSleepTimer", + listOf(), + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + null, + null, + ImmutableMethodImplementation( + 4, """ + sget-boolean v0, $INTEGRATIONS_CLASS_DESCRIPTOR + if-eqz v0, :dismiss + iget-object v1, v3, $musicPlaybackControlsMethodToCall + invoke-static {v1}, $sleepTimerStaticMethodToCall + move-result-object v0 + iget-object v1, v3, $musicPlaybackControlsMethodToCall + invoke-virtual {v0, v1}, $sleepTimerFinalMethodToCall + const/4 v0, 0x0 + sput-boolean v0, $INTEGRATIONS_CLASS_DESCRIPTOR + :dismiss + return-void + """.toInstructions(), null, null + ) + ).toMutable() + ) + } ?: return MusicPlaybackControlsClickFingerprint.toErrorResult() + + return PatchResultSuccess() + } + private companion object { + const val INTEGRATIONS_CLASS_DESCRIPTOR = "$MUSIC_MISC_PATH/HookShareButtonPatch;->isShareButtonClicked:Z" + var musicPlaybackControlsMethodToCall: String? = null + } +}