fix(YouTube - Remove background playback restrictions): Enable for Shorts as well (#3671)

This commit is contained in:
Zain 2024-10-27 03:57:43 +07:00 committed by oSumAtrIX
parent 7e1bdab520
commit 7db1a7751d
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
5 changed files with 68 additions and 38 deletions

View File

@ -1,5 +1,6 @@
package app.revanced.extension.youtube.patches; package app.revanced.extension.youtube.patches;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.youtube.shared.PlayerType; import app.revanced.extension.youtube.shared.PlayerType;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -8,10 +9,10 @@ public class BackgroundPlaybackPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static boolean allowBackgroundPlayback(boolean original) { public static boolean isBackgroundPlaybackAllowed(boolean original) {
if (original) return true; if (original) return true;
// Steps to verify most edge cases: // Steps to verify most edge cases (with Shorts background playback set to off):
// 1. Open a regular video // 1. Open a regular video
// 2. Minimize app (PIP should appear) // 2. Minimize app (PIP should appear)
// 3. Reopen app // 3. Reopen app
@ -22,13 +23,13 @@ public class BackgroundPlaybackPatch {
// 7. Close the Short // 7. Close the Short
// 8. Resume playing the regular video // 8. Resume playing the regular video
// 9. Minimize the app (PIP should appear) // 9. Minimize the app (PIP should appear)
if (!VideoInformation.lastVideoIdIsShort()) { if (!VideoInformation.lastVideoIdIsShort()) {
return true; // Definitely is not a Short. return true; // Definitely is not a Short.
} }
// Might be a Short, or might be a prior regular video on screen again after a Short was closed. // TODO: Add better hook.
// This incorrectly prevents PIP if player is in WATCH_WHILE_MINIMIZED after closing a Short, // Might be a Shorts, or might be a prior regular video on screen again after a Shorts was closed.
// This incorrectly prevents PIP if player is in WATCH_WHILE_MINIMIZED after closing a Shorts,
// But there's no way around this unless an additional hook is added to definitively detect // But there's no way around this unless an additional hook is added to definitively detect
// the Shorts player is on screen. This use case is unusual anyways so it's not a huge concern. // the Shorts player is on screen. This use case is unusual anyways so it's not a huge concern.
return !PlayerType.getCurrent().isNoneHiddenOrMinimized(); return !PlayerType.getCurrent().isNoneHiddenOrMinimized();
@ -37,10 +38,7 @@ public class BackgroundPlaybackPatch {
/** /**
* Injection point. * Injection point.
*/ */
public static boolean overrideBackgroundPlaybackAvailable() { public static boolean isBackgroundShortsPlaybackAllowed(boolean original) {
// This could be done entirely in the patch, return !Settings.DISABLE_SHORTS_BACKGROUND_PLAYBACK.get();
// but having a unique method to search for makes manually inspecting the patched apk much easier.
return true;
} }
} }

View File

@ -214,6 +214,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true); public static final BooleanSetting SWITCH_CREATE_WITH_NOTIFICATIONS_BUTTON = new BooleanSetting("revanced_switch_create_with_notifications_button", TRUE, true);
// Shorts // Shorts
public static final BooleanSetting DISABLE_SHORTS_BACKGROUND_PLAYBACK = new BooleanSetting("revanced_shorts_disable_background_playback", FALSE);
public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE); public static final BooleanSetting DISABLE_RESUMING_SHORTS_PLAYER = new BooleanSetting("revanced_disable_resuming_shorts_player", FALSE);
public static final BooleanSetting HIDE_SHORTS_HOME = new BooleanSetting("revanced_hide_shorts_home", FALSE); public static final BooleanSetting HIDE_SHORTS_HOME = new BooleanSetting("revanced_hide_shorts_home", FALSE);
public static final BooleanSetting HIDE_SHORTS_SUBSCRIPTIONS = new BooleanSetting("revanced_hide_shorts_subscriptions", FALSE); public static final BooleanSetting HIDE_SHORTS_SUBSCRIPTIONS = new BooleanSetting("revanced_hide_shorts_subscriptions", FALSE);

View File

@ -1,30 +1,33 @@
package app.revanced.patches.youtube.misc.backgroundplayback 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.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.instructions import app.revanced.patcher.extensions.InstructionExtensions.instructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch import app.revanced.patcher.patch.resourcePatch
import app.revanced.patches.all.misc.resources.addResources
import app.revanced.patches.all.misc.resources.addResourcesPatch
import app.revanced.patches.shared.misc.mapping.get import app.revanced.patches.shared.misc.mapping.get
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
import app.revanced.patches.shared.misc.mapping.resourceMappings import app.revanced.patches.shared.misc.mapping.resourceMappings
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch import app.revanced.patches.youtube.misc.playertype.playerTypeHookPatch
import app.revanced.patches.youtube.misc.settings.PreferenceScreen
import app.revanced.patches.youtube.misc.settings.settingsPatch import app.revanced.patches.youtube.misc.settings.settingsPatch
import app.revanced.patches.youtube.video.information.videoInformationPatch import app.revanced.patches.youtube.video.information.videoInformationPatch
import app.revanced.util.addInstructionsAtControlFlowLabel import app.revanced.util.addInstructionsAtControlFlowLabel
import app.revanced.util.findInstructionIndicesReversedOrThrow import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction 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.reference.MethodReference import com.android.tools.smali.dexlib2.iface.reference.MethodReference
internal var prefBackgroundAndOfflineCategoryId = -1L internal var prefBackgroundAndOfflineCategoryId = -1L
private set private set
private val backgroundPlaybackResourcePatch = resourcePatch { private val backgroundPlaybackResourcePatch = resourcePatch {
dependsOn(resourceMappingPatch) dependsOn(resourceMappingPatch, addResourcesPatch)
execute { execute {
prefBackgroundAndOfflineCategoryId = resourceMappings["string", "pref_background_and_offline_category"] prefBackgroundAndOfflineCategoryId = resourceMappings["string", "pref_background_and_offline_category"]
@ -58,45 +61,54 @@ val backgroundPlaybackPatch = bytecodePatch(
val backgroundPlaybackManagerMatch by backgroundPlaybackManagerFingerprint() val backgroundPlaybackManagerMatch by backgroundPlaybackManagerFingerprint()
val backgroundPlaybackSettingsMatch by backgroundPlaybackSettingsFingerprint() val backgroundPlaybackSettingsMatch by backgroundPlaybackSettingsFingerprint()
val shortsBackgroundPlaybackFeatureFlagMatch by shortsBackgroundPlaybackFeatureFlagFingerprint()
val backgroundPlaybackManagerShortsMatch by backgroundPlaybackManagerShortsFingerprint()
val kidsBackgroundPlaybackPolicyControllerMatch by kidsBackgroundPlaybackPolicyControllerFingerprint() val kidsBackgroundPlaybackPolicyControllerMatch by kidsBackgroundPlaybackPolicyControllerFingerprint()
execute { context -> execute { context ->
backgroundPlaybackManagerMatch.mutableMethod.apply { addResources("youtube", "misc.backgroundplayback.backgroundPlaybackPatch")
findInstructionIndicesReversedOrThrow(Opcode.RETURN).forEach { index ->
val register = getInstruction<OneRegisterInstruction>(index).registerA
addInstructionsAtControlFlowLabel( PreferenceScreen.SHORTS.addPreferences(
index, SwitchPreference("revanced_shorts_disable_background_playback")
""" )
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->allowBackgroundPlayback(Z)Z
move-result v$register arrayOf(
""", backgroundPlaybackManagerMatch to "isBackgroundPlaybackAllowed",
) backgroundPlaybackManagerShortsMatch to "isBackgroundShortsPlaybackAllowed"
).forEach { (match, integrationsMethod) ->
match.mutableMethod.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 // Enable background playback option in YouTube settings
backgroundPlaybackSettingsMatch.mutableMethod.apply { backgroundPlaybackSettingsMatch.mutableMethod.apply {
val booleanCalls = instructions.withIndex() val booleanCalls = instructions.withIndex().filter {
.filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" } it.value.getReference<MethodReference>()?.returnType == "Z"
}
val settingsBooleanIndex = booleanCalls.elementAt(1).index val settingsBooleanIndex = booleanCalls.elementAt(1).index
val settingsBooleanMethod = context.navigate(this).at(settingsBooleanIndex).mutable() val settingsBooleanMethod = context.navigate(this).at(settingsBooleanIndex).mutable()
settingsBooleanMethod.addInstructions( settingsBooleanMethod.returnEarly(true)
0,
"""
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->overrideBackgroundPlaybackAvailable()Z
move-result v0
return v0
""",
)
} }
// Force allowing background play for Shorts.
shortsBackgroundPlaybackFeatureFlagMatch.mutableMethod.returnEarly(true)
// Force allowing background play for videos labeled for kids. // Force allowing background play for videos labeled for kids.
kidsBackgroundPlaybackPolicyControllerMatch.mutableMethod.addInstruction( kidsBackgroundPlaybackPolicyControllerMatch.mutableMethod.returnEarly()
0,
"return-void",
)
} }
} }

View File

@ -70,3 +70,17 @@ internal val kidsBackgroundPlaybackPolicyControllerFingerprint = fingerprint {
) )
literal { 5 } literal { 5 }
} }
internal val backgroundPlaybackManagerShortsFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
returns("Z")
parameters("L")
literal { 151635310 }
}
internal val shortsBackgroundPlaybackFeatureFlagFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
returns("Z")
parameters()
literal { 45415425 }
}

View File

@ -86,6 +86,11 @@ This is because Crowdin requires temporarily flattening this file and removing t
<string name="revanced_settings_screen_11_misc_title">Misc</string> <string name="revanced_settings_screen_11_misc_title">Misc</string>
<string name="revanced_settings_screen_12_video_title">Video</string> <string name="revanced_settings_screen_12_video_title">Video</string>
</patch> </patch>
<patch id="misc.backgroundplayback.backgroundPlaybackPatch">
<string name="revanced_shorts_disable_background_playback_title">Disable Shorts background play</string>
<string name="revanced_shorts_disable_background_playback_summary_on">Shorts background play is disabled</string>
<string name="revanced_shorts_disable_background_playback_summary_off">Shorts background play is enabled</string>
</patch>
<patch id="misc.debugging.enableDebuggingPatch"> <patch id="misc.debugging.enableDebuggingPatch">
<string name="revanced_debug_screen_title">Debugging</string> <string name="revanced_debug_screen_title">Debugging</string>
<string name="revanced_debug_screen_summary">Enable or disable debugging options</string> <string name="revanced_debug_screen_summary">Enable or disable debugging options</string>