From 78e577d2601e4caea6d64b352335d71e6f9785e3 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Fri, 26 May 2023 14:46:53 +0200 Subject: [PATCH 1/5] Make some constants private and annotate params --- .../newpipe/settings/SettingMigrations.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java index 1bfaec6c2..bf691dc28 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java @@ -4,6 +4,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.util.Log; +import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; import org.schabi.newpipe.R; @@ -30,9 +31,9 @@ public final class SettingMigrations { private static final String TAG = SettingMigrations.class.toString(); private static SharedPreferences sp; - public static final Migration MIGRATION_0_1 = new Migration(0, 1) { + private static final Migration MIGRATION_0_1 = new Migration(0, 1) { @Override - public void migrate(final Context context) { + public void migrate(@NonNull final Context context) { // We changed the content of the dialog which opens when sharing a link to NewPipe // by removing the "open detail page" option. // Therefore, show the dialog once again to ensure users need to choose again and are @@ -44,9 +45,9 @@ public final class SettingMigrations { } }; - public static final Migration MIGRATION_1_2 = new Migration(1, 2) { + private static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override - protected void migrate(final Context context) { + protected void migrate(@NonNull final Context context) { // The new application workflow introduced in #2907 allows minimizing videos // while playing to do other stuff within the app. // For an even better workflow, we minimize a stream when switching the app to play in @@ -63,9 +64,9 @@ public final class SettingMigrations { } }; - public static final Migration MIGRATION_2_3 = new Migration(2, 3) { + private static final Migration MIGRATION_2_3 = new Migration(2, 3) { @Override - protected void migrate(final Context context) { + protected void migrate(@NonNull final Context context) { // Storage Access Framework implementation was improved in #5415, allowing the modern // and standard way to access folders and files to be used consistently everywhere. // We reset the setting to its default value, i.e. "use SAF", since now there are no @@ -79,9 +80,9 @@ public final class SettingMigrations { } }; - public static final Migration MIGRATION_3_4 = new Migration(3, 4) { + private static final Migration MIGRATION_3_4 = new Migration(3, 4) { @Override - protected void migrate(final Context context) { + protected void migrate(@NonNull final Context context) { // Pull request #3546 added support for choosing the type of search suggestions to // show, replacing the on-off switch used before, so migrate the previous user choice @@ -108,9 +109,9 @@ public final class SettingMigrations { } }; - public static final Migration MIGRATION_4_5 = new Migration(4, 5) { + private static final Migration MIGRATION_4_5 = new Migration(4, 5) { @Override - protected void migrate(final Context context) { + protected void migrate(@NonNull final Context context) { final boolean brightness = sp.getBoolean("brightness_gesture_control", true); final boolean volume = sp.getBoolean("volume_gesture_control", true); @@ -144,10 +145,10 @@ public final class SettingMigrations { /** * Version number for preferences. Must be incremented every time a migration is necessary. */ - public static final int VERSION = 5; + private static final int VERSION = 5; - public static void initMigrations(final Context context, final boolean isFirstRun) { + public static void initMigrations(@NonNull final Context context, final boolean isFirstRun) { // setup migrations and check if there is something to do sp = PreferenceManager.getDefaultSharedPreferences(context); final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); @@ -212,7 +213,7 @@ public final class SettingMigrations { return oldVersion >= currentVersion; } - protected abstract void migrate(Context context); + protected abstract void migrate(@NonNull Context context); } From 8b63b437d8542da898681230a683a92e7a50a7bc Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 18 Jul 2023 09:53:00 +0200 Subject: [PATCH 2/5] Disable media tunneling if the device is known for not supporting it Revert removing the Utils related to media tunneling. --- .../newpipe/settings/NewPipeSettings.java | 18 ++++++++ .../newpipe/settings/SettingMigrations.java | 14 ++++++- .../org/schabi/newpipe/util/DeviceUtils.java | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index 16df646f9..9e246574e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -76,6 +76,10 @@ public final class NewPipeSettings { saveDefaultVideoDownloadDirectory(context); saveDefaultAudioDownloadDirectory(context); + + if (isFirstRun) { // NOSONAR: isFirstRun is never null + setMediaTunneling(context); + } } static void saveDefaultVideoDownloadDirectory(final Context context) { @@ -152,4 +156,18 @@ public final class NewPipeSettings { return showSearchSuggestions(context, sharedPreferences, R.string.show_remote_search_suggestions_key); } + + /** + * Check if device does not support media tunneling + * and disable that exoplayer feature if necessary. + * @see DeviceUtils#shouldSupportMediaTunneling() + * @param context + */ + public static void setMediaTunneling(@NonNull final Context context) { + if (!DeviceUtils.shouldSupportMediaTunneling()) { + PreferenceManager.getDefaultSharedPreferences(context).edit() + .putBoolean(context.getString(R.string.disable_media_tunneling_key), true) + .apply(); + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java index bf691dc28..8b8dddbad 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java @@ -128,6 +128,17 @@ public final class SettingMigrations { } }; + private static final Migration MIGRATION_5_6 = new Migration(5, 6) { + @Override + protected void migrate(@NonNull final Context context) { + // PR #8875 added a new settings page for exoplayer introducing a specific setting + // to disable media tunneling. However, media tunneling should be disabled by default + // for some devices, because they are known for not supporting media tunneling + // which can result in a black screen while playing videos. + NewPipeSettings.setMediaTunneling(context); + } + }; + /** * List of all implemented migrations. *

@@ -140,12 +151,13 @@ public final class SettingMigrations { MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, + MIGRATION_5_6, }; /** * Version number for preferences. Must be incremented every time a migration is necessary. */ - private static final int VERSION = 5; + private static final int VERSION = 6; public static void initMigrations(@NonNull final Context context, final boolean isFirstRun) { diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index f656c6144..7111b8de9 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -36,6 +36,31 @@ public final class DeviceUtils { private static Boolean isTV = null; private static Boolean isFireTV = null; + /* + * Devices that do not support media tunneling + */ + + /** + * Formuler Z8 Pro, Z8, CC, Z Alpha, Z+ Neo. + */ + private static final boolean HI3798MV200 = Build.VERSION.SDK_INT == 24 + && Build.DEVICE.equals("Hi3798MV200"); + /** + * Zephir TS43UHD-2. + */ + private static final boolean CVT_MT5886_EU_1G = Build.VERSION.SDK_INT == 24 + && Build.DEVICE.equals("cvt_mt5886_eu_1g"); + /** + * Hilife TV. + */ + private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25 + && Build.DEVICE.equals("RealtekATV"); + /** + * Philips QM16XE. + */ + private static final boolean QM16XE_U = Build.VERSION.SDK_INT == 23 + && Build.DEVICE.equals("QM16XE_U"); + private DeviceUtils() { } @@ -224,4 +249,20 @@ public final class DeviceUtils { return point.y; } } + + /** + * Some devices have broken tunneled video playback but claim to support it. + * See https://github.com/TeamNewPipe/NewPipe/issues/5911 + * @Note Add a new {@link org.schabi.newpipe.settings.SettingMigrations.Migration} which calls + * {@link org.schabi.newpipe.settings.NewPipeSettings#setMediaTunneling(Context)} + * when adding a new device to the method + * @return {@code false} if affected device; {@code true} otherwise + */ + public static boolean shouldSupportMediaTunneling() { + // Maintainers note: add a new SettingsMigration which calls + return !HI3798MV200 + && !CVT_MT5886_EU_1G + && !REALTEKATV + && !QM16XE_U; + } } From 1db73370a7219e64b472c77b57f9436c2abb4fcf Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sat, 29 Jul 2023 22:08:24 +0200 Subject: [PATCH 3/5] Ensure that imports handle disabling media tunneling correctly Store in preferences whether media tunneling was disabled automatically. Show info in ExoPlayer settings if media tunneling was disabled autmatically. --- .../settings/ContentSettingsFragment.java | 40 ++++++++++++++++++- .../settings/ContentSettingsManager.kt | 3 ++ .../settings/ExoPlayerSettingsFragment.java | 31 ++++++++++++++ .../newpipe/settings/NewPipeSettings.java | 2 + .../org/schabi/newpipe/util/DeviceUtils.java | 2 +- app/src/main/res/values/settings_keys.xml | 1 + app/src/main/res/values/strings.xml | 3 +- 7 files changed, 78 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 434056b20..38a1fd8f8 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -15,6 +15,7 @@ import android.widget.Toast; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult; +import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; import androidx.preference.Preference; @@ -230,8 +231,11 @@ public class ContentSettingsFragment extends BasePreferenceFragment { }) .setPositiveButton(R.string.ok, (dialog, which) -> { dialog.dismiss(); - manager.loadSharedPreferences(PreferenceManager - .getDefaultSharedPreferences(requireContext())); + final Context context = requireContext(); + final SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + manager.loadSharedPreferences(prefs); + cleanImport(context, prefs); finishImport(importDataUri); }) .show(); @@ -243,6 +247,38 @@ public class ContentSettingsFragment extends BasePreferenceFragment { } } + /** + * Remove settings that are not supposed to be imported on different devices + * and reset them to default values. + * @param context the context used for the import + * @param prefs the preferences used while running the import + */ + private void cleanImport(@NonNull final Context context, + @NonNull final SharedPreferences prefs) { + // Check if media tunnelling needs to be disabled automatically, + // if it was disabled automatically in the imported preferences. + final String tunnelingKey = context.getString(R.string.disable_media_tunneling_key); + final String automaticTunnelingKey = + context.getString(R.string.disabled_media_tunneling_automatically_key); + // R.string.disable_media_tunneling_key should always be true + // if R.string.disabled_media_tunneling_automatically_key equals 1, + // but we double check here just to be sure and to avoid regressions + // caused by possible later modification of the media tunneling functionality. + // R.string.disabled_media_tunneling_automatically_key == 0: + // automatic value overridden by user in settings + // R.string.disabled_media_tunneling_automatically_key == -1: not set + final boolean wasMediaTunnelingEnabledAutomatically = + prefs.getInt(automaticTunnelingKey, -1) == 1 + && prefs.getBoolean(tunnelingKey, false); + if (wasMediaTunnelingEnabledAutomatically) { + prefs.edit() + .putInt(automaticTunnelingKey, -1) + .putBoolean(tunnelingKey, false) + .apply(); + NewPipeSettings.setMediaTunneling(context); + } + } + /** * Save import path and restart system. * diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt index 8adf6a649..92be93a29 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt @@ -67,6 +67,9 @@ class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) { return ZipHelper.extractFileFromZip(file, fileLocator.settings.path, "newpipe.settings") } + /** + * Remove all shared preferences from the app and load the preferences supplied to the manager. + */ fun loadSharedPreferences(preferences: SharedPreferences) { try { val preferenceEditor = preferences.edit() diff --git a/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java index 7e740f869..1cceea336 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java @@ -1,8 +1,14 @@ package org.schabi.newpipe.settings; +import android.content.SharedPreferences; import android.os.Bundle; import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.SwitchPreferenceCompat; + +import org.schabi.newpipe.R; public class ExoPlayerSettingsFragment extends BasePreferenceFragment { @@ -10,5 +16,30 @@ public class ExoPlayerSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(@Nullable final Bundle savedInstanceState, @Nullable final String rootKey) { addPreferencesFromResourceRegistry(); + + final String disableMediaTunnelingAutomaticallyKey = + getString(R.string.disabled_media_tunneling_automatically_key); + final SwitchPreferenceCompat disableMediaTunnelingPref = + (SwitchPreferenceCompat) requirePreference(R.string.disable_media_tunneling_key); + final SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(requireContext()); + final boolean mediaTunnelingAutomaticallyEnabled = + prefs.getInt(disableMediaTunnelingAutomaticallyKey, -1) == 1; + final String summaryText = getString(R.string.disable_media_tunneling_summary); + disableMediaTunnelingPref.setSummary(mediaTunnelingAutomaticallyEnabled + ? summaryText + getString(R.string.disable_media_tunneling_automatic_info) + : summaryText); + + disableMediaTunnelingPref.setOnPreferenceChangeListener((Preference p, Object enabled) -> { + if (Boolean.FALSE.equals(enabled)) { + PreferenceManager.getDefaultSharedPreferences(requireContext()) + .edit() + .putInt(disableMediaTunnelingAutomaticallyKey, 0) + .apply(); + // the info text might have been shown before + p.setSummary(R.string.disable_media_tunneling_summary); + } + return true; + }); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index 9e246574e..7057f0ec9 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -167,6 +167,8 @@ public final class NewPipeSettings { if (!DeviceUtils.shouldSupportMediaTunneling()) { PreferenceManager.getDefaultSharedPreferences(context).edit() .putBoolean(context.getString(R.string.disable_media_tunneling_key), true) + .putInt(context.getString( + R.string.disabled_media_tunneling_automatically_key), 1) .apply(); } } diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index 7111b8de9..111072a96 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -255,7 +255,7 @@ public final class DeviceUtils { * See https://github.com/TeamNewPipe/NewPipe/issues/5911 * @Note Add a new {@link org.schabi.newpipe.settings.SettingMigrations.Migration} which calls * {@link org.schabi.newpipe.settings.NewPipeSettings#setMediaTunneling(Context)} - * when adding a new device to the method + * when adding a new device to the method. * @return {@code false} if affected device; {@code true} otherwise */ public static boolean shouldSupportMediaTunneling() { diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index eebe29d81..b2e2925f3 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -1382,6 +1382,7 @@ exoplayer_settings_key disable_media_tunneling_key + disabled_media_tunneling_automatically_key use_exoplayer_decoder_fallback_key always_use_exoplayer_set_output_surface_workaround_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 75acedf9e..e4fcdeedc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -480,7 +480,8 @@ Show original time ago on items Original texts from services will be visible in stream items Disable media tunneling - Disable media tunneling if you experience a black screen or stuttering on video playback + Disable media tunneling if you experience a black screen or stuttering on video playback. + Media tunneling was disabled by default on your device because your device model is known to not support it. Show image indicators Show Picasso colored ribbons on top of images indicating their source: red for network, blue for disk and green for memory Show \"Crash the player\" From 40d102fcb5f3424f94e6ea64e2db39357cb8be2b Mon Sep 17 00:00:00 2001 From: TobiGr Date: Tue, 18 Jul 2023 21:27:28 +0200 Subject: [PATCH 4/5] Disable media tunneling by default on new devices Sony BRAVIA_VH1, BRAVIA_VH2, BRAVIA_ATV2, BRAVIA_ATV3_4K Phillips 4K (O)LED TV (PH7M_EU_5596) Panasonic 4KTV-JUP (TX_50JXW834) Bouygtel4K (HMB9213NW) --- .../org/schabi/newpipe/util/DeviceUtils.java | 57 +++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index 111072a96..096cf9523 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -36,10 +36,8 @@ public final class DeviceUtils { private static Boolean isTV = null; private static Boolean isFireTV = null; - /* - * Devices that do not support media tunneling - */ + // region: devices not supporting media tunneling /** * Formuler Z8 Pro, Z8, CC, Z Alpha, Z+ Neo. */ @@ -55,11 +53,53 @@ public final class DeviceUtils { */ private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25 && Build.DEVICE.equals("RealtekATV"); + /** + *

Phillips 4K (O)LED TV.

+ * Supports custom ROMs with different API levels + */ + private static final boolean PH7M_EU_5596 = Build.VERSION.SDK_INT >= 26 + && Build.DEVICE.equals("PH7M_EU_5596"); /** * Philips QM16XE. */ private static final boolean QM16XE_U = Build.VERSION.SDK_INT == 23 && Build.DEVICE.equals("QM16XE_U"); + /** + *

Sony Bravia VH1.

+ * Processor: MT5895 + */ + private static final boolean BRAVIA_VH1 = Build.VERSION.SDK_INT == 29 + && Build.DEVICE.equals("BRAVIA_VH1"); + /** + *

Sony Bravia VH2.

+ * This includes model A90J. + */ + private static final boolean BRAVIA_VH2 = Build.VERSION.SDK_INT == 29 + && Build.DEVICE.equals("BRAVIA_VH2"); + /** + *

Sony Bravia Android TV platform 2.

+ * Uses a MediaTek MT5891 (MT5596) SoC. + * @see + * https://github.com/CiNcH83/bravia_atv2 + */ + private static final boolean BRAVIA_ATV2 = Build.DEVICE.equals("BRAVIA_ATV2"); + /** + *

Sony Bravia Android TV platform 3 4K.

+ * Uses ARM MT5891 and a {@link #BRAVIA_ATV2} motherboard. + * @see + * https://browser.geekbench.com/v4/cpu/9101105 + */ + private static final boolean BRAVIA_ATV3_4K = Build.DEVICE.equals("BRAVIA_ATV3_4K"); + /** + * Panasonic 4KTV-JUP. + */ + private static final boolean TX_50JXW834 = Build.DEVICE.equals("TX_50JXW834"); + /** + *

Bouygtel4K / Bouygues Telecom Bbox 4K.

+ * Reported at https://github.com/TeamNewPipe/NewPipe/pull/10122#issuecomment-1638475769 + */ + private static final boolean HMB9213NW = Build.DEVICE.equals("HMB9213NW"); + // endregion private DeviceUtils() { } @@ -251,7 +291,7 @@ public final class DeviceUtils { } /** - * Some devices have broken tunneled video playback but claim to support it. + *

Some devices have broken tunneled video playback but claim to support it.

* See https://github.com/TeamNewPipe/NewPipe/issues/5911 * @Note Add a new {@link org.schabi.newpipe.settings.SettingMigrations.Migration} which calls * {@link org.schabi.newpipe.settings.NewPipeSettings#setMediaTunneling(Context)} @@ -263,6 +303,13 @@ public final class DeviceUtils { return !HI3798MV200 && !CVT_MT5886_EU_1G && !REALTEKATV - && !QM16XE_U; + && !QM16XE_U + && !BRAVIA_VH1 + && !BRAVIA_VH2 + && !BRAVIA_ATV2 // crash caused by exiting full screen + && !BRAVIA_ATV3_4K // crash caused by exiting full screen + && !PH7M_EU_5596 + && !TX_50JXW834 + && !HMB9213NW; // crash caused by exiting full screen } } From d6a1170ddb4bc67c5f008c334158eccc901b02e9 Mon Sep 17 00:00:00 2001 From: TobiGr Date: Mon, 31 Jul 2023 21:34:20 +0200 Subject: [PATCH 5/5] Replace settings migration with automatic check for device blacklist version --- .../settings/ContentSettingsFragment.java | 4 +- .../settings/ExoPlayerSettingsFragment.java | 12 ++-- .../newpipe/settings/NewPipeSettings.java | 41 ++++++++++--- .../newpipe/settings/SettingMigrations.java | 17 +----- .../org/schabi/newpipe/util/DeviceUtils.java | 57 +++++++++++++------ app/src/main/res/values/settings_keys.xml | 1 + 6 files changed, 86 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 38a1fd8f8..ee34f01dd 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -267,10 +267,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment { // R.string.disabled_media_tunneling_automatically_key == 0: // automatic value overridden by user in settings // R.string.disabled_media_tunneling_automatically_key == -1: not set - final boolean wasMediaTunnelingEnabledAutomatically = + final boolean wasMediaTunnelingDisabledAutomatically = prefs.getInt(automaticTunnelingKey, -1) == 1 && prefs.getBoolean(tunnelingKey, false); - if (wasMediaTunnelingEnabledAutomatically) { + if (wasMediaTunnelingDisabledAutomatically) { prefs.edit() .putInt(automaticTunnelingKey, -1) .putBoolean(tunnelingKey, false) diff --git a/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java index 1cceea336..14dd0c409 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ExoPlayerSettingsFragment.java @@ -17,24 +17,24 @@ public class ExoPlayerSettingsFragment extends BasePreferenceFragment { @Nullable final String rootKey) { addPreferencesFromResourceRegistry(); - final String disableMediaTunnelingAutomaticallyKey = + final String disabledMediaTunnelingAutomaticallyKey = getString(R.string.disabled_media_tunneling_automatically_key); final SwitchPreferenceCompat disableMediaTunnelingPref = (SwitchPreferenceCompat) requirePreference(R.string.disable_media_tunneling_key); final SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(requireContext()); - final boolean mediaTunnelingAutomaticallyEnabled = - prefs.getInt(disableMediaTunnelingAutomaticallyKey, -1) == 1; + final boolean mediaTunnelingAutomaticallyDisabled = + prefs.getInt(disabledMediaTunnelingAutomaticallyKey, -1) == 1; final String summaryText = getString(R.string.disable_media_tunneling_summary); - disableMediaTunnelingPref.setSummary(mediaTunnelingAutomaticallyEnabled - ? summaryText + getString(R.string.disable_media_tunneling_automatic_info) + disableMediaTunnelingPref.setSummary(mediaTunnelingAutomaticallyDisabled + ? summaryText + " " + getString(R.string.disable_media_tunneling_automatic_info) : summaryText); disableMediaTunnelingPref.setOnPreferenceChangeListener((Preference p, Object enabled) -> { if (Boolean.FALSE.equals(enabled)) { PreferenceManager.getDefaultSharedPreferences(requireContext()) .edit() - .putInt(disableMediaTunnelingAutomaticallyKey, 0) + .putInt(disabledMediaTunnelingAutomaticallyKey, 0) .apply(); // the info text might have been shown before p.setSummary(R.string.disable_media_tunneling_summary); diff --git a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java index 7057f0ec9..2cca08072 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java +++ b/app/src/main/java/org/schabi/newpipe/settings/NewPipeSettings.java @@ -1,5 +1,7 @@ package org.schabi.newpipe.settings; +import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; + import android.content.Context; import android.content.SharedPreferences; import android.os.Build; @@ -15,8 +17,6 @@ import org.schabi.newpipe.util.DeviceUtils; import java.io.File; import java.util.Set; -import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; - /* * Created by k3b on 07.01.2016. * @@ -61,7 +61,7 @@ public final class NewPipeSettings { } // first run migrations, then setDefaultValues, since the latter requires the correct types - SettingMigrations.initMigrations(context, isFirstRun); + SettingMigrations.runMigrationsIfNeeded(context, isFirstRun); // readAgain is true so that if new settings are added their default value is set PreferenceManager.setDefaultValues(context, R.xml.main_settings, true); @@ -77,9 +77,7 @@ public final class NewPipeSettings { saveDefaultVideoDownloadDirectory(context); saveDefaultAudioDownloadDirectory(context); - if (isFirstRun) { // NOSONAR: isFirstRun is never null - setMediaTunneling(context); - } + disableMediaTunnelingIfNecessary(context, isFirstRun); } static void saveDefaultVideoDownloadDirectory(final Context context) { @@ -157,6 +155,28 @@ public final class NewPipeSettings { R.string.show_remote_search_suggestions_key); } + private static void disableMediaTunnelingIfNecessary(@NonNull final Context context, + final boolean isFirstRun) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final String disabledTunnelingKey = context.getString(R.string.disable_media_tunneling_key); + final String disabledTunnelingAutomaticallyKey = + context.getString(R.string.disabled_media_tunneling_automatically_key); + final String blacklistVersionKey = + context.getString(R.string.media_tunneling_device_blacklist_version); + + final int lastMediaTunnelingUpdate = prefs.getInt(blacklistVersionKey, 0); + final boolean wasDeviceBlacklistUpdated = + DeviceUtils.MEDIA_TUNNELING_DEVICE_BLACKLIST_VERSION != lastMediaTunnelingUpdate; + final boolean wasMediaTunnelingEnabledByUser = + prefs.getInt(disabledTunnelingAutomaticallyKey, -1) == 0 + && !prefs.getBoolean(disabledTunnelingKey, false); + + if (Boolean.TRUE.equals(isFirstRun) + || (wasDeviceBlacklistUpdated && !wasMediaTunnelingEnabledByUser)) { + setMediaTunneling(context); + } + } + /** * Check if device does not support media tunneling * and disable that exoplayer feature if necessary. @@ -164,12 +184,19 @@ public final class NewPipeSettings { * @param context */ public static void setMediaTunneling(@NonNull final Context context) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if (!DeviceUtils.shouldSupportMediaTunneling()) { - PreferenceManager.getDefaultSharedPreferences(context).edit() + prefs.edit() .putBoolean(context.getString(R.string.disable_media_tunneling_key), true) .putInt(context.getString( R.string.disabled_media_tunneling_automatically_key), 1) + .putInt(context.getString(R.string.media_tunneling_device_blacklist_version), + DeviceUtils.MEDIA_TUNNELING_DEVICE_BLACKLIST_VERSION) .apply(); + } else { + prefs.edit() + .putInt(context.getString(R.string.media_tunneling_device_blacklist_version), + DeviceUtils.MEDIA_TUNNELING_DEVICE_BLACKLIST_VERSION).apply(); } } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java index 8b8dddbad..215caaa38 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java @@ -128,17 +128,6 @@ public final class SettingMigrations { } }; - private static final Migration MIGRATION_5_6 = new Migration(5, 6) { - @Override - protected void migrate(@NonNull final Context context) { - // PR #8875 added a new settings page for exoplayer introducing a specific setting - // to disable media tunneling. However, media tunneling should be disabled by default - // for some devices, because they are known for not supporting media tunneling - // which can result in a black screen while playing videos. - NewPipeSettings.setMediaTunneling(context); - } - }; - /** * List of all implemented migrations. *

@@ -151,16 +140,16 @@ public final class SettingMigrations { MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, - MIGRATION_5_6, }; /** * Version number for preferences. Must be incremented every time a migration is necessary. */ - private static final int VERSION = 6; + private static final int VERSION = 5; - public static void initMigrations(@NonNull final Context context, final boolean isFirstRun) { + public static void runMigrationsIfNeeded(@NonNull final Context context, + final boolean isFirstRun) { // setup migrations and check if there is something to do sp = PreferenceManager.getDefaultSharedPreferences(context); final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index 096cf9523..e9678c2b0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -36,20 +36,32 @@ public final class DeviceUtils { private static Boolean isTV = null; private static Boolean isFireTV = null; - - // region: devices not supporting media tunneling /** - * Formuler Z8 Pro, Z8, CC, Z Alpha, Z+ Neo. + *

The app version code that corresponds to the last update + * of the media tunneling device blacklist.

+ *

The value of this variable needs to be updated everytime a new device that does not + * support media tunneling to match the upcoming version code.

+ * @see #shouldSupportMediaTunneling() + */ + public static final int MEDIA_TUNNELING_DEVICE_BLACKLIST_VERSION = 994; + + // region: devices not supporting media tunneling / media tunneling blacklist + /** + *

Formuler Z8 Pro, Z8, CC, Z Alpha, Z+ Neo.

+ *

Blacklist reason: black screen

+ *

Board: HiSilicon Hi3798MV200

*/ private static final boolean HI3798MV200 = Build.VERSION.SDK_INT == 24 && Build.DEVICE.equals("Hi3798MV200"); /** - * Zephir TS43UHD-2. + *

Zephir TS43UHD-2.

+ *

Blacklist reason: black screen

*/ private static final boolean CVT_MT5886_EU_1G = Build.VERSION.SDK_INT == 24 && Build.DEVICE.equals("cvt_mt5886_eu_1g"); /** * Hilife TV. + *

Blacklist reason: black screen

*/ private static final boolean REALTEKATV = Build.VERSION.SDK_INT == 25 && Build.DEVICE.equals("RealtekATV"); @@ -60,19 +72,23 @@ public final class DeviceUtils { private static final boolean PH7M_EU_5596 = Build.VERSION.SDK_INT >= 26 && Build.DEVICE.equals("PH7M_EU_5596"); /** - * Philips QM16XE. + *

Philips QM16XE.

+ *

Blacklist reason: black screen

*/ private static final boolean QM16XE_U = Build.VERSION.SDK_INT == 23 && Build.DEVICE.equals("QM16XE_U"); /** *

Sony Bravia VH1.

- * Processor: MT5895 + *

Processor: MT5895

+ *

Blacklist reason: fullscreen crash / stuttering

*/ private static final boolean BRAVIA_VH1 = Build.VERSION.SDK_INT == 29 && Build.DEVICE.equals("BRAVIA_VH1"); /** *

Sony Bravia VH2.

- * This includes model A90J. + *

Blacklist reason: fullscreen crash; this includes model A90J as reported in + * + * #9023

*/ private static final boolean BRAVIA_VH2 = Build.VERSION.SDK_INT == 29 && Build.DEVICE.equals("BRAVIA_VH2"); @@ -85,18 +101,22 @@ public final class DeviceUtils { private static final boolean BRAVIA_ATV2 = Build.DEVICE.equals("BRAVIA_ATV2"); /** *

Sony Bravia Android TV platform 3 4K.

- * Uses ARM MT5891 and a {@link #BRAVIA_ATV2} motherboard. + *

Uses ARM MT5891 and a {@link #BRAVIA_ATV2} motherboard.

+ * * @see * https://browser.geekbench.com/v4/cpu/9101105 */ private static final boolean BRAVIA_ATV3_4K = Build.DEVICE.equals("BRAVIA_ATV3_4K"); /** - * Panasonic 4KTV-JUP. + *

Panasonic 4KTV-JUP.

+ *

Blacklist reason: fullscreen crash

*/ private static final boolean TX_50JXW834 = Build.DEVICE.equals("TX_50JXW834"); /** *

Bouygtel4K / Bouygues Telecom Bbox 4K.

- * Reported at https://github.com/TeamNewPipe/NewPipe/pull/10122#issuecomment-1638475769 + *

Blacklist reason: black screen; reported at + * + * #10122

*/ private static final boolean HMB9213NW = Build.DEVICE.equals("HMB9213NW"); // endregion @@ -292,24 +312,27 @@ public final class DeviceUtils { /** *

Some devices have broken tunneled video playback but claim to support it.

- * See https://github.com/TeamNewPipe/NewPipe/issues/5911 - * @Note Add a new {@link org.schabi.newpipe.settings.SettingMigrations.Migration} which calls - * {@link org.schabi.newpipe.settings.NewPipeSettings#setMediaTunneling(Context)} + *

This can cause a black video player surface while attempting to play a video or + * crashes while entering or exiting the full screen player. + * The issue effects Android TVs most commonly. + * See #5911 and + * #9023 for more info.

+ * @Note Update {@link #MEDIA_TUNNELING_DEVICE_BLACKLIST_VERSION} * when adding a new device to the method. * @return {@code false} if affected device; {@code true} otherwise */ public static boolean shouldSupportMediaTunneling() { - // Maintainers note: add a new SettingsMigration which calls + // Maintainers note: update MEDIA_TUNNELING_DEVICES_UPDATE_APP_VERSION_CODE return !HI3798MV200 && !CVT_MT5886_EU_1G && !REALTEKATV && !QM16XE_U && !BRAVIA_VH1 && !BRAVIA_VH2 - && !BRAVIA_ATV2 // crash caused by exiting full screen - && !BRAVIA_ATV3_4K // crash caused by exiting full screen + && !BRAVIA_ATV2 + && !BRAVIA_ATV3_4K && !PH7M_EU_5596 && !TX_50JXW834 - && !HMB9213NW; // crash caused by exiting full screen + && !HMB9213NW; } } diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index b2e2925f3..a41d41fdb 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -1383,6 +1383,7 @@ exoplayer_settings_key disable_media_tunneling_key disabled_media_tunneling_automatically_key + media_tunneling_device_blacklist_version use_exoplayer_decoder_fallback_key always_use_exoplayer_set_output_surface_workaround_key