Skip to content

Commit

Permalink
fix(YouTube - Remove background playback restriction): Play/Pause but…
Browse files Browse the repository at this point in the history
…ton not working in PiP mode
  • Loading branch information
inotia00 authored and anddea committed Feb 8, 2025
1 parent 597c7d7 commit 2f35f59
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package app.revanced.extension.youtube.patches.misc;

import app.revanced.extension.shared.settings.BooleanSetting;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType;
import app.revanced.extension.youtube.shared.ShortsPlayerState;

@SuppressWarnings("unused")
public class BackgroundPlaybackPatch {
private static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK =
Settings.DISABLE_SHORTS_BACKGROUND_PLAYBACK;

/**
* Injection point.
Expand All @@ -18,7 +22,7 @@ public static boolean isBackgroundPlaybackAllowed(boolean original) {
* Injection point.
*/
public static boolean isBackgroundShortsPlaybackAllowed(boolean original) {
return !Settings.DISABLE_SHORTS_BACKGROUND_PLAYBACK.get();
return !DISABLE_SHORTS_BACKGROUND_PLAYBACK.get();
}

}
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package app.revanced.patches.youtube.misc.backgroundplayback

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
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
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
Expand All @@ -32,22 +37,23 @@ val backgroundPlaybackPatch = bytecodePatch(
dependsOn(
playerTypeHookPatch,
settingsPatch,
versionCheckPatch,
)

execute {

arrayOf(
backgroundPlaybackManagerFingerprint to "isBackgroundPlaybackAllowed",
backgroundPlaybackManagerShortsFingerprint to "isBackgroundShortsPlaybackAllowed",
).forEach { (fingerprint, integrationsMethod) ->
).forEach { (fingerprint, extensionsMethod) ->
fingerprint.methodOrThrow().apply {
findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index ->
val register = getInstruction<OneRegisterInstruction>(index).registerA

addInstructionsAtControlFlowLabel(
index,
"""
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$integrationsMethod(Z)Z
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->$extensionsMethod(Z)Z
move-result v$register
""",
)
Expand All @@ -68,7 +74,30 @@ val backgroundPlaybackPatch = bytecodePatch(
}

// Force allowing background play for Shorts.
shortsBackgroundPlaybackFeatureFlagFingerprint.methodOrThrow().returnEarly(true)
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<OneRegisterInstruction>(insertIndex).registerA

addInstruction(
insertIndex,
"const/4 v$insertRegister, 0x0"
)
}
}
}
}

// Force allowing background play for videos labeled for kids.
kidsBackgroundPlaybackPolicyControllerFingerprint.methodOrThrow(
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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),
)

0 comments on commit 2f35f59

Please sign in to comment.