From 6caaf58d404497a54011bd6d346278133ff2a3c8 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 13 Jan 2022 09:53:57 +0000 Subject: [PATCH] Update test relying on network type detection to run on all API levels. This ensures we test the API level specific logic, in particular around 5G-NSA detection. Robolectric has a remaining bug that it doesn't support listening to service state changes. Hence, we need to ignore some tests on these API levels still until this is fixed. PiperOrigin-RevId: 421505951 --- .../upstream/DefaultBandwidthMeterTest.java | 147 ++++++++++++++++-- 1 file changed, 137 insertions(+), 10 deletions(-) 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 c084b330b9..450222a71f 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,9 +25,11 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.Uri; +import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import androidx.media3.common.C; import androidx.media3.common.util.NetworkTypeObserver; +import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSpec; import androidx.media3.test.utils.FakeClock; @@ -42,9 +44,11 @@ import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowNetworkInfo; +import org.robolectric.shadows.ShadowTelephonyManager; /** Unit test for {@link DefaultBandwidthMeter}. */ @RunWith(AndroidJUnit4.class) +@Config(sdk = Config.ALL_SDKS) // Test all SDKs because network detection logic changed over time. public final class DefaultBandwidthMeterTest { private static final int SIMULATED_TRANSFER_COUNT = 100; @@ -58,8 +62,6 @@ public final class DefaultBandwidthMeterTest { private NetworkInfo networkInfo2g; private NetworkInfo networkInfo3g; private NetworkInfo networkInfo4g; - // TODO: Add tests covering 5G-NSA networks. Not testable right now because we need to set the - // TelephonyDisplayInfo on API 31, which isn't available for Robolectric yet. private NetworkInfo networkInfo5gSa; private NetworkInfo networkInfoEthernet; @@ -185,9 +187,15 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimateEthernet).isGreaterThan(initialEstimate3g); } - @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4G_isGreaterThanEstimateFor2G() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + setActiveNetworkInfo(networkInfo4g); DefaultBandwidthMeter bandwidthMeter4g = new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); @@ -201,9 +209,15 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimate4g).isGreaterThan(initialEstimate2g); } - @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4G_isGreaterThanEstimateFor3G() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + setActiveNetworkInfo(networkInfo4g); DefaultBandwidthMeter bandwidthMeter4g = new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); @@ -233,18 +247,42 @@ public final class DefaultBandwidthMeterTest { } @Test - public void defaultInitialBitrateEstimate_for5gSa_isGreaterThanEstimateFor4g() { + @Config(minSdk = 29) // 5G detection support was added in API 29. + public void defaultInitialBitrateEstimate_for5gNsa_isGreaterThanEstimateFor4g() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + setActiveNetworkInfo(networkInfo4g); DefaultBandwidthMeter bandwidthMeter4g = new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); long initialEstimate4g = bandwidthMeter4g.getBitrateEstimate(); + setActiveNetworkInfo(networkInfo4g, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA); + DefaultBandwidthMeter bandwidthMeter5gNsa = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); + long initialEstimate5gNsa = bandwidthMeter5gNsa.getBitrateEstimate(); + + assertThat(initialEstimate5gNsa).isGreaterThan(initialEstimate4g); + } + + @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. + public void defaultInitialBitrateEstimate_for5gSa_isGreaterThanEstimateFor3g() { + setActiveNetworkInfo(networkInfo3g); + DefaultBandwidthMeter bandwidthMeter3g = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); + long initialEstimate3g = bandwidthMeter3g.getBitrateEstimate(); + setActiveNetworkInfo(networkInfo5gSa); DefaultBandwidthMeter bandwidthMeter5gSa = new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); long initialEstimate5gSa = bandwidthMeter5gSa.getBitrateEstimate(); - assertThat(initialEstimate5gSa).isGreaterThan(initialEstimate4g); + assertThat(initialEstimate5gSa).isGreaterThan(initialEstimate3g); } @Test @@ -326,10 +364,16 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow); } - @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void defaultInitialBitrateEstimate_for4g_forFastCountry_isGreaterThanEstimateForSlowCountry() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + setActiveNetworkInfo(networkInfo4g); setNetworkCountryIso(FAST_COUNTRY_ISO); DefaultBandwidthMeter bandwidthMeterFast = @@ -345,6 +389,32 @@ public final class DefaultBandwidthMeterTest { } @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. + public void + defaultInitialBitrateEstimate_for5gNsa_forFastCountry_isGreaterThanEstimateForSlowCountry() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + + setActiveNetworkInfo(networkInfo4g, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA); + setNetworkCountryIso(FAST_COUNTRY_ISO); + DefaultBandwidthMeter bandwidthMeterFast = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); + long initialEstimateFast = bandwidthMeterFast.getBitrateEstimate(); + + setNetworkCountryIso(SLOW_COUNTRY_ISO); + DefaultBandwidthMeter bandwidthMeterSlow = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build(); + long initialEstimateSlow = bandwidthMeterSlow.getBitrateEstimate(); + + assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow); + } + + @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. public void defaultInitialBitrateEstimate_for5gSa_forFastCountry_isGreaterThanEstimateForSlowCountry() { setActiveNetworkInfo(networkInfo5gSa); @@ -486,9 +556,15 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimate).isNotEqualTo(123456789); } - @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void initialBitrateEstimateOverwrite_for4G_whileConnectedTo4G_setsInitialEstimate() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + setActiveNetworkInfo(networkInfo4g); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()) @@ -499,7 +575,6 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimate).isEqualTo(123456789); } - @Config(sdk = 28) // TODO(b/190021699): Fix 4G tests to work on newer API levels @Test public void initialBitrateEstimateOverwrite_for4G_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { @@ -514,6 +589,41 @@ public final class DefaultBandwidthMeterTest { } @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. + public void initialBitrateEstimateOverwrite_for5gNsa_whileConnectedTo5gNsa_setsInitialEstimate() { + if (Util.SDK_INT == 29 || Util.SDK_INT == 30) { + // Robolectric doesn't support listening to service state changes, which we need on APIs 29 + // and 30 to run this test successfully. + // TODO(b/190021699): Update once Robolectric released support for this. + return; + } + + setActiveNetworkInfo(networkInfo4g, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA); + DefaultBandwidthMeter bandwidthMeter = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()) + .setInitialBitrateEstimate(C.NETWORK_TYPE_5G_NSA, 123456789) + .build(); + long initialEstimate = bandwidthMeter.getBitrateEstimate(); + + assertThat(initialEstimate).isEqualTo(123456789); + } + + @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. + public void + initialBitrateEstimateOverwrite_for5gNsa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { + setActiveNetworkInfo(networkInfo4g); + DefaultBandwidthMeter bandwidthMeter = + new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()) + .setInitialBitrateEstimate(C.NETWORK_TYPE_5G_NSA, 123456789) + .build(); + long initialEstimate = bandwidthMeter.getBitrateEstimate(); + + assertThat(initialEstimate).isNotEqualTo(123456789); + } + + @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedTo5gSa_setsInitialEstimate() { setActiveNetworkInfo(networkInfo5gSa); DefaultBandwidthMeter bandwidthMeter = @@ -526,6 +636,7 @@ public final class DefaultBandwidthMeterTest { } @Test + @Config(minSdk = 29) // 5G detection support was added in API 29. public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() { setActiveNetworkInfo(networkInfoWifi); @@ -638,11 +749,27 @@ public final class DefaultBandwidthMeterTest { assertThat(initialEstimateWithoutBuilder).isLessThan(50_000_000L); } - @SuppressWarnings("StickyBroadcast") private void setActiveNetworkInfo(NetworkInfo networkInfo) { + setActiveNetworkInfo(networkInfo, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); + } + + @SuppressWarnings("StickyBroadcast") + private void setActiveNetworkInfo(NetworkInfo networkInfo, int networkTypeOverride) { + // Set network info in ConnectivityManager and TelephonyDisplayInfo in TelephonyManager. Shadows.shadowOf(connectivityManager).setActiveNetworkInfo(networkInfo); + if (Util.SDK_INT >= 31) { + Object displayInfo = + ShadowTelephonyManager.createTelephonyDisplayInfo( + networkInfo.getType(), networkTypeOverride); + Shadows.shadowOf(telephonyManager).setTelephonyDisplayInfo(displayInfo); + } + // Create a sticky broadcast for the connectivity action because Roboletric isn't replying with + // the current network state if a receiver for this intent is registered. ApplicationProvider.getApplicationContext() .sendStickyBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); + // Trigger initialization of static network type observer. + NetworkTypeObserver.getInstance(ApplicationProvider.getApplicationContext()); + // Wait until all pending messages are handled and the network initialization is done. ShadowLooper.idleMainLooper(); }