Skip to content

Commit

Permalink
feat(YouTube - Remove background playback restrictions): Add PiP mode…
Browse files Browse the repository at this point in the history
… support in Shorts
  • Loading branch information
inotia00 authored and anddea committed Dec 17, 2024
1 parent 26d8ba6 commit 4fc44b2
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package app.revanced.extension.youtube.patches.misc;

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

@SuppressWarnings("unused")
public class BackgroundPlaybackPatch {

public static boolean allowBackgroundPlayback(boolean original) {
return original || ShortsPlayerState.getCurrent().isClosed();
/**
* Injection point.
*/
public static boolean isBackgroundPlaybackAllowed(boolean original) {
if (original) return true;
return ShortsPlayerState.getCurrent().isClosed();
}

/**
* Injection point.
*/
public static boolean isBackgroundShortsPlaybackAllowed(boolean original) {
return !Settings.DISABLE_SHORTS_BACKGROUND_PLAYBACK.get();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ public class Settings extends BaseSettings {

// PreferenceScreen: Shorts
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", TRUE);
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_disable_shorts_background_playback", FALSE);
public static final BooleanSetting HIDE_SHORTS_FLOATING_BUTTON = new BooleanSetting("revanced_hide_shorts_floating_button", TRUE);
public static final BooleanSetting HIDE_SHORTS_SHELF = new BooleanSetting("revanced_hide_shorts_shelf", TRUE, true);
public static final BooleanSetting HIDE_SHORTS_SHELF_CHANNEL = new BooleanSetting("revanced_hide_shorts_shelf_channel", FALSE);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
package app.revanced.patches.youtube.misc.backgroundplayback

import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
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.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.matchOrThrow
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getWalkerMethod
import app.revanced.util.fingerprint.originalMethodOrThrow
import app.revanced.util.getReference
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

private const val EXTENSION_CLASS_DESCRIPTOR =
"$MISC_PATH/BackgroundPlaybackPatch;"

@Suppress("unused")
val backgroundPlaybackPatch = bytecodePatch(
REMOVE_BACKGROUND_PLAYBACK_RESTRICTIONS.title,
Expand All @@ -35,69 +36,54 @@ val backgroundPlaybackPatch = bytecodePatch(

execute {

backgroundPlaybackManagerFingerprint.methodOrThrow().apply {
findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index ->
val register = getInstruction<OneRegisterInstruction>(index).registerA

// Replace to preserve control flow label.
replaceInstruction(
index,
"invoke-static { v$register }, $MISC_PATH/BackgroundPlaybackPatch;->allowBackgroundPlayback(Z)Z"
)

addInstructions(
index + 1,
"""
move-result v$register
return v$register
arrayOf(
backgroundPlaybackManagerFingerprint to "isBackgroundPlaybackAllowed",
backgroundPlaybackManagerShortsFingerprint to "isBackgroundShortsPlaybackAllowed",
).forEach { (fingerprint, integrationsMethod) ->
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
move-result v$register
""",
)
}
}
}

// Enable background playback option in YouTube settings
backgroundPlaybackSettingsFingerprint.methodOrThrow().apply {
val booleanCalls = implementation!!.instructions.withIndex()
.filter { instruction ->
((instruction.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z"
}
backgroundPlaybackSettingsFingerprint.originalMethodOrThrow().apply {
val booleanCalls = instructions.withIndex().filter {
it.value.getReference<MethodReference>()?.returnType == "Z"
}

val booleanIndex = booleanCalls.elementAt(1).index
val booleanMethod = getWalkerMethod(booleanIndex)
val settingsBooleanIndex = booleanCalls.elementAt(1).index
val settingsBooleanMethod by navigate(this).to(settingsBooleanIndex)

booleanMethod.addInstructions(
0, """
const/4 v0, 0x1
return v0
"""
)
settingsBooleanMethod.returnEarly(true)
}

// Force allowing background play for Shorts.
shortsBackgroundPlaybackFeatureFlagFingerprint.methodOrThrow().returnEarly(true)

// Force allowing background play for videos labeled for kids.
kidsBackgroundPlaybackPolicyControllerFingerprint.methodOrThrow(
kidsBackgroundPlaybackPolicyControllerParentFingerprint
).addInstruction(
0,
"return-void"
)

pipControllerFingerprint.matchOrThrow().let {
val targetMethod =
it.getWalkerMethod(it.patternMatch!!.endIndex)

targetMethod.apply {
val targetRegister = getInstruction<TwoRegisterInstruction>(0).registerA

addInstruction(
1,
"const/4 v$targetRegister, 0x1"
)
}
}
).returnEarly()

// region add settings

addPreference(REMOVE_BACKGROUND_PLAYBACK_RESTRICTIONS)
addPreference(
arrayOf(
"PREFERENCE_SCREEN: SHORTS",
"SETTINGS: DISABLE_SHORTS_BACKGROUND_PLAYBACK"
),
REMOVE_BACKGROUND_PLAYBACK_RESTRICTIONS
)

// endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,18 @@ internal val kidsBackgroundPlaybackPolicyControllerParentFingerprint = legacyFin
}
)

internal val pipControllerFingerprint = legacyFingerprint(
name = "pipControllerFingerprint",
returnType = "V",
internal val backgroundPlaybackManagerShortsFingerprint = legacyFingerprint(
name = "backgroundPlaybackManagerShortsFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
returnType = "Z",
parameters = listOf("L"),
literals = listOf(151635310L),
)

internal val shortsBackgroundPlaybackFeatureFlagFingerprint = legacyFingerprint(
name = "shortsBackgroundPlaybackFeatureFlagFingerprint",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z",
parameters = emptyList(),
opcodes = listOf(
Opcode.IF_NEZ,
Opcode.INVOKE_DIRECT
),
literals = listOf(151635310L),
literals = listOf(45415425L),
)
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,9 @@
<SwitchPreference android:title="@string/revanced_replace_channel_handle_title" android:key="revanced_replace_channel_handle" android:summaryOn="@string/revanced_replace_channel_handle_summary_on" android:summaryOff="@string/revanced_replace_channel_handle_summary_off" />
</PreferenceScreen>SETTINGS: SHORTS_COMPONENTS -->

<!-- SETTINGS: DISABLE_SHORTS_BACKGROUND_PLAYBACK
<SwitchPreference android:title="@string/revanced_disable_shorts_background_playback_title" android:key="revanced_disable_shorts_background_playback" android:summaryOn="@string/revanced_disable_shorts_background_playback_summary_on" android:summaryOff="@string/revanced_disable_shorts_background_playback_summary_off" />SETTINGS: DISABLE_SHORTS_BACKGROUND_PLAYBACK -->

<!-- SETTINGS: DISABLE_RESUMING_SHORTS_PLAYER
<SwitchPreference android:title="@string/revanced_disable_resuming_shorts_player_title" android:key="revanced_disable_resuming_shorts_player" android:summaryOn="@string/revanced_disable_resuming_shorts_player_summary_on" android:summaryOff="@string/revanced_disable_resuming_shorts_player_summary_off" />SETTINGS: DISABLE_RESUMING_SHORTS_PLAYER -->

Expand Down

0 comments on commit 4fc44b2

Please sign in to comment.