diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6fddb54979..c10d3d9ab0 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -16,6 +16,8 @@ for example when side-loading subtitles and changing the selected subtitle mid-playback ([#10248](https://github.com/google/ExoPlayer/issues/10248)). + * Stop detecting 5G-NSA network type on API 29 and 30. These playbacks + will assume a 4G network. * Track selection: * Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`, and promote `TrackSelectionOverride` to a top level class. diff --git a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java index 5caf81f176..e2e3f96044 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/NetworkTypeObserver.java @@ -25,8 +25,8 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; import android.os.Looper; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyCallback.DisplayInfoListener; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import androidx.annotation.GuardedBy; @@ -59,24 +59,6 @@ public final class NetworkTypeObserver { void onNetworkTypeChanged(@C.NetworkType int networkType); } - /* - * Static configuration that may need to be set at app startup time is located in a separate - * static Config class. This allows apps to set their desired config without incurring unnecessary - * class loading costs during startup. - */ - /** Configuration for {@link NetworkTypeObserver}. */ - public static final class Config { - - private static volatile boolean disable5GNsaDisambiguation; - - /** Disables logic to disambiguate 5G-NSA networks from 4G networks. */ - public static void disable5GNsaDisambiguation() { - disable5GNsaDisambiguation = true; - } - - private Config() {} - } - @Nullable private static NetworkTypeObserver staticInstance; private final Handler mainHandler; @@ -232,26 +214,16 @@ public final class NetworkTypeObserver { @Override public void onReceive(Context context, Intent intent) { @C.NetworkType int networkType = getNetworkTypeFromConnectivityManager(context); - if (Util.SDK_INT >= 29 - && !Config.disable5GNsaDisambiguation - && networkType == C.NETWORK_TYPE_4G) { + if (Util.SDK_INT >= 31 && networkType == C.NETWORK_TYPE_4G) { // Delay update of the network type to check whether this is actually 5G-NSA. try { - // We can't access TelephonyManager getters like getServiceState() directly as they - // require special permissions. Attaching a listener is permission-free because the - // callback data is censored to not include sensitive information. TelephonyManager telephonyManager = checkNotNull((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)); - TelephonyManagerListener listener = new TelephonyManagerListener(); - if (Util.SDK_INT < 31) { - telephonyManager.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); - } else { - // Display info information can only be requested without permission from API 31. - telephonyManager.listen(listener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED); - } + DisplayInfoCallback callback = new DisplayInfoCallback(); + telephonyManager.registerTelephonyCallback(context.getMainExecutor(), callback); // We are only interested in the initial response with the current state, so unregister // the listener immediately. - telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE); + telephonyManager.unregisterTelephonyCallback(callback); return; } catch (RuntimeException e) { // Ignore problems with listener registration and keep reporting as 4G. @@ -261,19 +233,9 @@ public final class NetworkTypeObserver { } } - private class TelephonyManagerListener extends PhoneStateListener { + @RequiresApi(31) + private final class DisplayInfoCallback extends TelephonyCallback implements DisplayInfoListener { - @Override - public void onServiceStateChanged(@Nullable ServiceState serviceState) { - // This workaround to check the toString output of ServiceState only works on API 29 and 30. - String serviceStateString = serviceState == null ? "" : serviceState.toString(); - boolean is5gNsa = - serviceStateString.contains("nrState=CONNECTED") - || serviceStateString.contains("nrState=NOT_RESTRICTED"); - updateNetworkType(is5gNsa ? C.NETWORK_TYPE_5G_NSA : C.NETWORK_TYPE_4G); - } - - @RequiresApi(31) @Override public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { int overrideNetworkType = telephonyDisplayInfo.getOverrideNetworkType(); diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java index 60b10f87b9..d2ca3e7f03 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/upstream/DefaultBandwidthMeterTest.java @@ -25,7 +25,6 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.Uri; -import android.telephony.ServiceState; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import androidx.media3.common.C; @@ -234,7 +233,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 31) // 5G-NSA detection is supported from API 31. public void defaultInitialBitrateEstimate_for5gNsa_isGreaterThanEstimateFor4g() { setActiveNetworkInfo(networkInfo4g); DefaultBandwidthMeter bandwidthMeter4g = @@ -250,7 +249,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 29) // 5G-SA detection is supported from API 29. public void defaultInitialBitrateEstimate_for5gSa_isGreaterThanEstimateFor3g() { setActiveNetworkInfo(networkInfo3g); DefaultBandwidthMeter bandwidthMeter3g = @@ -362,7 +361,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 31) // 5G-NSA detection is supported from API 31. public void defaultInitialBitrateEstimate_for5gNsa_forFastCountry_isGreaterThanEstimateForSlowCountry() { setActiveNetworkInfo(networkInfo4g, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA); @@ -380,7 +379,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 29) // 5G-SA detection support was added in API 29. public void defaultInitialBitrateEstimate_for5gSa_forFastCountry_isGreaterThanEstimateForSlowCountry() { setActiveNetworkInfo(networkInfo5gSa); @@ -548,7 +547,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 31) // 5G-NSA detection is supported from API 31. public void initialBitrateEstimateOverwrite_for5gNsa_whileConnectedTo5gNsa_setsInitialEstimate() { setActiveNetworkInfo(networkInfo4g, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA); DefaultBandwidthMeter bandwidthMeter = @@ -561,7 +560,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 31) // 5G-NSA detection is supported from API 31. public void initialBitrateEstimateOverwrite_for5gNsa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { setActiveNetworkInfo(networkInfo4g); @@ -575,7 +574,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 29) // 5G-SA detection is supported from API 29. public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedTo5gSa_setsInitialEstimate() { setActiveNetworkInfo(networkInfo5gSa); DefaultBandwidthMeter bandwidthMeter = @@ -588,7 +587,7 @@ public final class DefaultBandwidthMeterTest { } @Test - @Config(minSdk = 29) // 5G detection support was added in API 29. + @Config(minSdk = 29) // 5G-SA detection is supported from API 29. public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { setActiveNetworkInfo(networkInfoWifi); @@ -714,19 +713,6 @@ public final class DefaultBandwidthMeterTest { ShadowTelephonyManager.createTelephonyDisplayInfo( networkInfo.getType(), networkTypeOverride); Shadows.shadowOf(telephonyManager).setTelephonyDisplayInfo(displayInfo); - } else if (Util.SDK_INT >= 29) { - ServiceState serviceState = new ServiceState(); - if (networkTypeOverride == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { - // Replicate known platform hack that includes special string indicating 5G-NSA. - serviceState = - new ServiceState() { - @Override - public String toString() { - return "...nrState=CONNECTED..."; - } - }; - } - Shadows.shadowOf(telephonyManager).setServiceState(serviceState); } // Create a sticky broadcast for the connectivity action because Robolectric isn't replying with // the current network state if a receiver for this intent is registered.