diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/BackgroundPlaybackPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/BackgroundPlaybackPatch.java index 20cb70a4b..e6172078d 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/BackgroundPlaybackPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/misc/BackgroundPlaybackPatch.java @@ -18,16 +18,6 @@ public class BackgroundPlaybackPatch { return ShortsPlayerState.getCurrent().isClosed(); } - /** - * Injection point. - */ - public static boolean isBackgroundShortsPlaybackAllowed() { - if (PlayerType.getCurrent().isNoneHiddenOrMinimized()) { - return !DISABLE_SHORTS_BACKGROUND_PLAYBACK.get(); - } - return false; - } - /** * Injection point. */ diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt index 0401a305f..fdee59c81 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/BackgroundPlaybackPatch.kt @@ -1,6 +1,6 @@ package app.revanced.patches.youtube.misc.backgroundplayback -import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.instructions import app.revanced.patcher.patch.bytecodePatch @@ -8,10 +8,14 @@ import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PAC import app.revanced.patches.youtube.utils.extension.Constants.MISC_PATH import app.revanced.patches.youtube.utils.patch.PatchList.REMOVE_BACKGROUND_PLAYBACK_RESTRICTIONS import app.revanced.patches.youtube.utils.playertype.playerTypeHookPatch +import app.revanced.patches.youtube.utils.playservice.is_19_34_or_greater +import app.revanced.patches.youtube.utils.playservice.versionCheckPatch import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference import app.revanced.patches.youtube.utils.settings.settingsPatch import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.findInstructionIndicesReversedOrThrow +import app.revanced.util.fingerprint.injectLiteralInstructionBooleanCall +import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import app.revanced.util.fingerprint.originalMethodOrThrow import app.revanced.util.getReference @@ -33,6 +37,7 @@ val backgroundPlaybackPatch = bytecodePatch( dependsOn( playerTypeHookPatch, settingsPatch, + versionCheckPatch, ) execute { @@ -69,18 +74,31 @@ val backgroundPlaybackPatch = bytecodePatch( } // Force allowing background play for Shorts. - shortsBackgroundPlaybackFeatureFlagFingerprint.methodOrThrow().addInstructionsWithLabels( - 0, - """ - invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->isBackgroundShortsPlaybackAllowed()Z - move-result v0 - if-eqz v0, :disabled - return v0 - :disabled - nop - """ + shortsBackgroundPlaybackFeatureFlagFingerprint.injectLiteralInstructionBooleanCall( + SHORTS_BACKGROUND_PLAYBACK_FEATURE_FLAG, + "$EXTENSION_CLASS_DESCRIPTOR->isBackgroundShortsPlaybackAllowed(Z)Z" ) + // Fix PiP mode issue. + if (is_19_34_or_greater) { + arrayOf( + backgroundPlaybackManagerCairoFragmentPrimaryFingerprint, + backgroundPlaybackManagerCairoFragmentSecondaryFingerprint + ).forEach { fingerprint -> + fingerprint.matchOrThrow(backgroundPlaybackManagerCairoFragmentParentFingerprint).let { + it.method.apply { + val insertIndex = it.patternMatch!!.startIndex + 4 + val insertRegister = getInstruction(insertIndex).registerA + + addInstruction( + insertIndex, + "const/4 v$insertRegister, 0x0" + ) + } + } + } + } + // Force allowing background play for videos labeled for kids. kidsBackgroundPlaybackPolicyControllerFingerprint.methodOrThrow( kidsBackgroundPlaybackPolicyControllerParentFingerprint diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt index 7fd5299c8..7c89ea6a5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/backgroundplayback/Fingerprints.kt @@ -1,6 +1,7 @@ package app.revanced.patches.youtube.misc.backgroundplayback import app.revanced.patches.youtube.utils.PLAYER_RESPONSE_MODEL_CLASS_DESCRIPTOR +import app.revanced.patches.youtube.utils.fix.cairo.cairoFragmentConfigFingerprint import app.revanced.patches.youtube.utils.resourceid.backgroundCategory import app.revanced.util.fingerprint.legacyFingerprint import app.revanced.util.getReference @@ -64,10 +65,72 @@ internal val backgroundPlaybackManagerShortsFingerprint = legacyFingerprint( literals = listOf(151635310L), ) +internal val backgroundPlaybackManagerCairoFragmentParentFingerprint = legacyFingerprint( + name = "backgroundPlaybackManagerCairoFragmentParentFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + parameters = emptyList(), + strings = listOf("yt_android_settings"), + customFingerprint = { method, _ -> + method.definingClass != "Lcom/google/android/apps/youtube/app/settings/AboutPrefsFragment;" + } +) + +/** + * Matches using the class found in [backgroundPlaybackManagerCairoFragmentParentFingerprint]. + * + * In this method, the value of the cairoFragmentConfig - [cairoFragmentConfigFingerprint] - must be disabled. + * If not, sometimes the pause / play button may not work when entering the PIP mode. + * See [ReVanced_Extended#2764](https://github.com/inotia00/ReVanced_Extended/issues/2764). + */ +internal val backgroundPlaybackManagerCairoFragmentPrimaryFingerprint = legacyFingerprint( + name = "backgroundPlaybackManagerCairoFragmentPrimaryFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + parameters = emptyList(), + opcodes = listOf( + Opcode.INVOKE_SUPER, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, // Method of [cairoFragmentConfigFingerprint] + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.CONST_4, + Opcode.IPUT_OBJECT, + ), +) + +/** + * Matches using the class found in [backgroundPlaybackManagerCairoFragmentParentFingerprint]. + * + * In this method, the value of the cairoFragmentConfig - [cairoFragmentConfigFingerprint] - must be disabled. + * If not, sometimes the pause / play button may not work when entering the PIP mode. + * See [ReVanced_Extended#2764](https://github.com/inotia00/ReVanced_Extended/issues/2764). + */ +internal val backgroundPlaybackManagerCairoFragmentSecondaryFingerprint = legacyFingerprint( + name = "backgroundPlaybackManagerCairoFragmentSecondaryFingerprint", + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "V", + parameters = emptyList(), + opcodes = listOf( + Opcode.INVOKE_SUPER, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, // Method of [cairoFragmentConfigFingerprint] + Opcode.MOVE_RESULT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.NEW_INSTANCE, + ), +) + +internal const val SHORTS_BACKGROUND_PLAYBACK_FEATURE_FLAG = 45415425L + internal val shortsBackgroundPlaybackFeatureFlagFingerprint = legacyFingerprint( name = "shortsBackgroundPlaybackFeatureFlagFingerprint", accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, returnType = "Z", parameters = emptyList(), - literals = listOf(45415425L), + literals = listOf(SHORTS_BACKGROUND_PLAYBACK_FEATURE_FLAG), ) \ No newline at end of file