diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java index 4669e999a1..e8f9c83517 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/BaseSettings.java @@ -3,7 +3,6 @@ import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static app.revanced.extension.shared.settings.Setting.parent; -import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.SpoofiOSAvailability; import app.revanced.extension.shared.spoof.AudioStreamLanguage; import app.revanced.extension.shared.spoof.ClientType; @@ -23,8 +22,6 @@ public class BaseSettings { public static final BooleanSetting SPOOF_VIDEO_STREAMS = new BooleanSetting("revanced_spoof_video_streams", TRUE, true, "revanced_spoof_video_streams_user_dialog_message"); public static final EnumSetting SPOOF_VIDEO_STREAMS_LANGUAGE = new EnumSetting<>("revanced_spoof_video_streams_language", AudioStreamLanguage.DEFAULT, parent(SPOOF_VIDEO_STREAMS)); - public static final BooleanSetting SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC = new BooleanSetting("revanced_spoof_video_streams_ios_force_avc", FALSE, true, - "revanced_spoof_video_streams_ios_force_avc_user_dialog_message", new SpoofiOSAvailability()); - public static final EnumSetting SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.IOS, true, parent(SPOOF_VIDEO_STREAMS)); + public static final EnumSetting SPOOF_VIDEO_STREAMS_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_video_streams_client_type", ClientType.ANDROID_VR, true, parent(SPOOF_VIDEO_STREAMS)); } diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/ClientType.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/ClientType.java index e281cf50e4..af274deb77 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/ClientType.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/ClientType.java @@ -4,13 +4,10 @@ import androidx.annotation.Nullable; -import app.revanced.extension.shared.settings.BaseSettings; - public enum ClientType { - // Specific purpose for age restricted, or private videos, because the iOS client is not logged in. // https://dumps.tadiphone.dev/dumps/oculus/eureka - ANDROID_VR(28, - "ANDROID_VR", + ANDROID_VR( + 28, "Quest 3", "12", "com.google.android.apps.youtube.vr.oculus/1.56.21 (Linux; U; Android 12; GB) gzip", @@ -18,33 +15,24 @@ public enum ClientType { "1.56.21", true ), - // Specific for kids videos. - IOS(5, - "IOS", - forceAVC() - ? "iPhone12,5" // 11 Pro Max (last device with iOS 13) - : "iPhone17,2", // 16 Pro Max - // iOS 13 and earlier uses only AVC. 14+ adds VP9 and AV1. - forceAVC() - ? "13.7.17H35" // Last release of iOS 13. - : "18.1.1.22B91", - forceAVC() - ? "com.google.ios.youtube/17.40.5 (iPhone; U; CPU iOS 13_7 like Mac OS X)" - : "com.google.ios.youtube/19.49.5 (iPhone; U; CPU iOS 18_1_1 like Mac OS X)", - null, - // Version number should be a valid iOS release. - // https://www.ipa4fun.com/history/185230 - forceAVC() - // Some newer versions can also force AVC, - // but 17.40 is the last version that supports iOS 13. - ? "17.40.5" - : "19.49.5", - false - ); - - private static boolean forceAVC() { - return BaseSettings.SPOOF_VIDEO_STREAMS_IOS_FORCE_AVC.get(); - } + ANDROID_UNPLUGGED( + 29, + "Google TV Streamer", + "14", + "com.google.android.apps.youtube.unplugged/8.49.0 (Linux; U; Android 14; GB) gzip", + "34", + "8.49.0", + true + ), + ANDROID_CREATOR( + 14, + "Android", + "11", + "com.google.android.apps.youtube.creator/24.45.100 (Linux; U; Android 11) gzip", + "30", + "24.45.100", + true +); /** * YouTube @@ -87,7 +75,6 @@ private static boolean forceAVC() { public final boolean canLogin; ClientType(int id, - String clientName, String deviceModel, String osVersion, String userAgent, @@ -95,7 +82,7 @@ private static boolean forceAVC() { String clientVersion, boolean canLogin) { this.id = id; - this.clientName = clientName; + this.clientName = name(); this.deviceModel = deviceModel; this.osVersion = osVersion; this.userAgent = userAgent; diff --git a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/SpoofVideoStreamsPatch.java b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/SpoofVideoStreamsPatch.java index fe3d684bb5..e55306e5ad 100644 --- a/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/SpoofVideoStreamsPatch.java +++ b/extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/SpoofVideoStreamsPatch.java @@ -18,9 +18,6 @@ public class SpoofVideoStreamsPatch { private static final boolean SPOOF_STREAMING_DATA = BaseSettings.SPOOF_VIDEO_STREAMS.get(); - private static final boolean FIX_HLS_CURRENT_TIME = SPOOF_STREAMING_DATA - && BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS; - /** * Any unreachable ip address. Used to intentionally fail requests. */ @@ -34,20 +31,19 @@ private static boolean isPatchIncluded() { return false; // Modified during patching. } - public static final class NotSpoofingAndroidVrAvailability implements Setting.Availability { + public static final class NotSpoofingAndroidAvailability implements Setting.Availability { @Override public boolean isAvailable() { if (SpoofVideoStreamsPatch.isPatchIncluded()) { - EnumSetting clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE; - return clientType.isAvailable() && clientType.get() != ClientType.ANDROID_VR; + EnumSetting setting = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE; + ClientType type = setting.get(); + return setting.isAvailable() && type.androidSdkVersion == null; } return true; } } - - /** * Injection point. * Blocks /get_watch requests by returning an unreachable URI. @@ -190,25 +186,4 @@ public static byte[] removeVideoPlaybackPostBody(Uri uri, int method, byte[] pos return postData; } - - /** - * Injection point. - * - * Fixes iOS livestreams starting from the beginning. - */ - public static boolean fixHLSCurrentTime(boolean original) { - if (FIX_HLS_CURRENT_TIME) { - return false; - } - - return original; - } - - public static final class SpoofiOSAvailability implements Setting.Availability { - @Override - public boolean isAvailable() { - return BaseSettings.SPOOF_VIDEO_STREAMS.get() - && BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get() == ClientType.IOS; - } - } } diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java index c2995dd34f..b147249d8f 100644 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java +++ b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java @@ -7,7 +7,7 @@ import static app.revanced.extension.shared.settings.Setting.migrateOldSettingToNew; import static app.revanced.extension.shared.settings.Setting.parent; import static app.revanced.extension.shared.settings.Setting.parentsAny; -import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.NotSpoofingAndroidVrAvailability; +import static app.revanced.extension.shared.spoof.SpoofVideoStreamsPatch.NotSpoofingAndroidAvailability; import static app.revanced.extension.youtube.patches.ChangeStartPagePatch.StartPage; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHideExpandCloseAvailability; import static app.revanced.extension.youtube.patches.MiniplayerPatch.MiniplayerHorizontalDragAvailability; @@ -54,7 +54,7 @@ public class Settings extends BaseSettings { public static final StringSetting CUSTOM_PLAYBACK_SPEEDS = new StringSetting("revanced_custom_playback_speeds", "0.25\n0.5\n0.75\n0.9\n0.95\n1.0\n1.05\n1.1\n1.25\n1.5\n1.75\n2.0\n3.0\n4.0\n5.0", true); // Audio - public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new NotSpoofingAndroidVrAvailability()); + public static final BooleanSetting FORCE_ORIGINAL_AUDIO = new BooleanSetting("revanced_force_original_audio", FALSE, new NotSpoofingAndroidAvailability()); // Ads public static final BooleanSetting HIDE_BUTTONED_ADS = new BooleanSetting("revanced_hide_buttoned_ads", TRUE); diff --git a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java b/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java deleted file mode 100644 index 4a9be0d5fd..0000000000 --- a/extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/preference/SpoofStreamingDataSideEffectsPreference.java +++ /dev/null @@ -1,85 +0,0 @@ -package app.revanced.extension.youtube.settings.preference; - -import static app.revanced.extension.shared.StringRef.str; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.Preference; -import android.preference.PreferenceManager; -import android.util.AttributeSet; - -import androidx.annotation.Nullable; - -import app.revanced.extension.shared.Logger; -import app.revanced.extension.shared.Utils; -import app.revanced.extension.shared.settings.BaseSettings; -import app.revanced.extension.shared.settings.Setting; -import app.revanced.extension.shared.spoof.ClientType; - -@SuppressWarnings({"deprecation", "unused"}) -public class SpoofStreamingDataSideEffectsPreference extends Preference { - - @Nullable - private ClientType currentClientType; - - private final SharedPreferences.OnSharedPreferenceChangeListener listener = (sharedPreferences, str) -> { - // Because this listener may run before the ReVanced settings fragment updates Settings, - // this could show the prior config and not the current. - // - // Push this call to the end of the main run queue, - // so all other listeners are done and Settings is up to date. - Utils.runOnMainThread(this::updateUI); - }; - - public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public SpoofStreamingDataSideEffectsPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public SpoofStreamingDataSideEffectsPreference(Context context) { - super(context); - } - - private void addChangeListener() { - Setting.preferences.preferences.registerOnSharedPreferenceChangeListener(listener); - } - - private void removeChangeListener() { - Setting.preferences.preferences.unregisterOnSharedPreferenceChangeListener(listener); - } - - @Override - protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { - super.onAttachedToHierarchy(preferenceManager); - updateUI(); - addChangeListener(); - } - - @Override - protected void onPrepareForRemoval() { - super.onPrepareForRemoval(); - removeChangeListener(); - } - - private void updateUI() { - ClientType clientType = BaseSettings.SPOOF_VIDEO_STREAMS_CLIENT_TYPE.get(); - if (currentClientType == clientType) { - return; - } - - Logger.printDebug(() -> "Updating spoof stream side effects preference"); - setEnabled(BaseSettings.SPOOF_VIDEO_STREAMS.get()); - - String key = "revanced_spoof_video_streams_about_" - + clientType.name().toLowerCase(); - setTitle(str(key + "_title")); - setSummary(str(key + "_summary")); - } -} diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt index c4a581c52a..683529a71b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/Fingerprints.kt @@ -1,7 +1,6 @@ package app.revanced.patches.shared.misc.spoof import app.revanced.patcher.fingerprint -import app.revanced.util.literal import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -112,16 +111,6 @@ internal val buildMediaDataSourceFingerprint = fingerprint { ) } -internal const val HLS_CURRENT_TIME_FEATURE_FLAG = 45355374L - -internal val hlsCurrentTimeFingerprint = fingerprint { - accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL) - parameters("Z", "L") - literal { - HLS_CURRENT_TIME_FEATURE_FLAG - } -} - internal val patchIncludedExtensionMethodFingerprint = fingerprint { accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC) returns("Z") diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt index 417873c709..30c7bf9c9b 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/misc/spoof/SpoofVideoStreamsPatch.kt @@ -12,7 +12,6 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu import app.revanced.patches.all.misc.resources.addResourcesPatch import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow -import app.revanced.util.insertFeatureFlagBooleanOverride import app.revanced.util.returnEarly import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -209,15 +208,6 @@ fun spoofVideoStreamsPatch( } // endregion - // region Fix iOS livestream current time. - - hlsCurrentTimeFingerprint.method.insertFeatureFlagBooleanOverride( - HLS_CURRENT_TIME_FEATURE_FLAG, - "$EXTENSION_CLASS_DESCRIPTOR->fixHLSCurrentTime(Z)Z" - ) - - // endregion - executeBlock() } } diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt index fa53200bf5..674854a4c5 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/misc/spoof/SpoofVideoStreamsPatch.kt @@ -44,12 +44,7 @@ val spoofVideoStreamsPatch = spoofVideoStreamsPatch({ "revanced_spoof_video_streams_language", summaryKey = null ), - SwitchPreference("revanced_spoof_video_streams_ios_force_avc"), - NonInteractivePreference( - // Requires a key and title but the actual text is chosen at runtime. - key = "revanced_spoof_video_streams_about_android_vr", - tag = "app.revanced.extension.youtube.settings.preference.SpoofStreamingDataSideEffectsPreference" - ), + NonInteractivePreference("revanced_spoof_video_streams_about_android") ), ), ) diff --git a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt index 94a80d908d..1e11044923 100644 --- a/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/youtube/video/audio/ForceOriginalAudioPatch.kt @@ -31,7 +31,8 @@ private const val EXTENSION_CLASS_DESCRIPTOR = @Suppress("unused") val forceOriginalAudioPatch = bytecodePatch( name = "Force original audio", - description = "Adds an option to always use the original audio track.", + description = "Adds an option to always use the original audio track. " + + "This patch does nothing if 'Spoof video streams' is enabled.", ) { dependsOn( sharedExtensionPatch, diff --git a/patches/src/main/resources/addresources/values/arrays.xml b/patches/src/main/resources/addresources/values/arrays.xml index 3ce8ff5e39..e3b93e71d6 100644 --- a/patches/src/main/resources/addresources/values/arrays.xml +++ b/patches/src/main/resources/addresources/values/arrays.xml @@ -4,12 +4,14 @@ Android VR - iOS + Android TV + Android Creator ANDROID_VR - IOS + ANDROID_UNPLUGGED + ANDROID_CREATOR @string/revanced_spoof_video_streams_language_DEFAULT diff --git a/patches/src/main/resources/addresources/values/strings.xml b/patches/src/main/resources/addresources/values/strings.xml index dc826d49b9..2d994070bb 100644 --- a/patches/src/main/resources/addresources/values/strings.xml +++ b/patches/src/main/resources/addresources/values/strings.xml @@ -1297,17 +1297,8 @@ Enabling this can unlock higher video qualities" Video playback may not work" Turning off this setting may cause video playback issues. Default client - Force AVC (H.264) - Video codec is forced to AVC (H.264) - Video codec is determined automatically - "Enabling this might improve battery life and fix playback stuttering. - -AVC has a maximum resolution of 1080p, Opus audio codec is not available, and video playback will use more internet data than VP9 or AV1." - iOS spoofing side effects - "• Private kids videos may not play -• Videos end 1 second early" - Android VR spoofing side effects - "• Kids videos may not play + Android spoofing side effects + "• Kids videos may not play • Audio track menu is missing • Stable volume is not available • Force original audio is not available"