Add 5G-NSA detection.
PiperOrigin-RevId: 364607555
This commit is contained in:
parent
c202d406fb
commit
b35c81124d
@ -930,8 +930,8 @@ public final class C {
|
||||
/**
|
||||
* Network connection type. One of {@link #NETWORK_TYPE_UNKNOWN}, {@link #NETWORK_TYPE_OFFLINE},
|
||||
* {@link #NETWORK_TYPE_WIFI}, {@link #NETWORK_TYPE_2G}, {@link #NETWORK_TYPE_3G}, {@link
|
||||
* #NETWORK_TYPE_4G}, {@link #NETWORK_TYPE_5G}, {@link #NETWORK_TYPE_CELLULAR_UNKNOWN}, {@link
|
||||
* #NETWORK_TYPE_ETHERNET} or {@link #NETWORK_TYPE_OTHER}.
|
||||
* #NETWORK_TYPE_4G}, {@link #NETWORK_TYPE_5G_SA}, {@link #NETWORK_TYPE_5G_NSA}, {@link
|
||||
* #NETWORK_TYPE_CELLULAR_UNKNOWN}, {@link #NETWORK_TYPE_ETHERNET} or {@link #NETWORK_TYPE_OTHER}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@ -942,7 +942,8 @@ public final class C {
|
||||
NETWORK_TYPE_2G,
|
||||
NETWORK_TYPE_3G,
|
||||
NETWORK_TYPE_4G,
|
||||
NETWORK_TYPE_5G,
|
||||
NETWORK_TYPE_5G_SA,
|
||||
NETWORK_TYPE_5G_NSA,
|
||||
NETWORK_TYPE_CELLULAR_UNKNOWN,
|
||||
NETWORK_TYPE_ETHERNET,
|
||||
NETWORK_TYPE_OTHER
|
||||
@ -960,8 +961,10 @@ public final class C {
|
||||
public static final int NETWORK_TYPE_3G = 4;
|
||||
/** Network type for a 4G cellular connection. */
|
||||
public static final int NETWORK_TYPE_4G = 5;
|
||||
/** Network type for a 5G cellular connection. */
|
||||
public static final int NETWORK_TYPE_5G = 9;
|
||||
/** Network type for a 5G stand-alone (SA) cellular connection. */
|
||||
public static final int NETWORK_TYPE_5G_SA = 9;
|
||||
/** Network type for a 5G non-stand-alone (NSA) cellular connection. */
|
||||
public static final int NETWORK_TYPE_5G_NSA = 10;
|
||||
/**
|
||||
* Network type for cellular connections which cannot be mapped to one of {@link
|
||||
* #NETWORK_TYPE_2G}, {@link #NETWORK_TYPE_3G}, or {@link #NETWORK_TYPE_4G}.
|
||||
|
@ -207,7 +207,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
||||
|
||||
private static Map<Integer, Long> getInitialBitrateEstimatesForCountry(String countryCode) {
|
||||
List<Integer> groupIndices = getCountryGroupIndices(countryCode);
|
||||
Map<Integer, Long> result = new HashMap<>(/* initialCapacity= */ 6);
|
||||
Map<Integer, Long> result = new HashMap<>(/* initialCapacity= */ 8);
|
||||
result.put(C.NETWORK_TYPE_UNKNOWN, DEFAULT_INITIAL_BITRATE_ESTIMATE);
|
||||
result.put(
|
||||
C.NETWORK_TYPE_WIFI,
|
||||
@ -222,7 +222,12 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
||||
C.NETWORK_TYPE_4G,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G.get(groupIndices.get(COUNTRY_GROUP_INDEX_4G)));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_5G,
|
||||
C.NETWORK_TYPE_5G_NSA,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA.get(
|
||||
groupIndices.get(COUNTRY_GROUP_INDEX_5G_NSA)));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_5G_SA,
|
||||
// TODO: Retrieve actual 5G-SA estimates.
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA.get(
|
||||
groupIndices.get(COUNTRY_GROUP_INDEX_5G_NSA)));
|
||||
// Assume default Wifi speed for Ethernet to prevent using the slower fallback.
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.util;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -23,6 +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.TelephonyManager;
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -196,7 +200,7 @@ public final class NetworkTypeObserver {
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return C.NETWORK_TYPE_4G;
|
||||
case TelephonyManager.NETWORK_TYPE_NR:
|
||||
return Util.SDK_INT >= 29 ? C.NETWORK_TYPE_5G : C.NETWORK_TYPE_UNKNOWN;
|
||||
return Util.SDK_INT >= 29 ? C.NETWORK_TYPE_5G_SA : C.NETWORK_TYPE_UNKNOWN;
|
||||
case TelephonyManager.NETWORK_TYPE_IWLAN:
|
||||
return C.NETWORK_TYPE_WIFI;
|
||||
case TelephonyManager.NETWORK_TYPE_GSM:
|
||||
@ -211,7 +215,36 @@ public final class NetworkTypeObserver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@C.NetworkType int networkType = getNetworkTypeFromConnectivityManager(context);
|
||||
if (networkType == C.NETWORK_TYPE_4G && Util.SDK_INT >= 29 && Util.SDK_INT < 31) {
|
||||
// Delay update of the network type to check whether this is actually 5G-NSA.
|
||||
try {
|
||||
// We can't access TelephonyManager.getServiceState() directly as it requires special
|
||||
// permissions. Attaching a listener is permission-free.
|
||||
TelephonyManager telephonyManager =
|
||||
checkNotNull((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
|
||||
ServiceStateListener listener = new ServiceStateListener();
|
||||
telephonyManager.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
|
||||
// We are only interested in the initial response with the current state, so unregister
|
||||
// the listener immediately.
|
||||
telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
|
||||
return;
|
||||
} catch (RuntimeException e) {
|
||||
// Ignore problems with listener registration and keep reporting as 4G.
|
||||
}
|
||||
}
|
||||
updateNetworkType(networkType);
|
||||
}
|
||||
}
|
||||
|
||||
private class ServiceStateListener extends PhoneStateListener {
|
||||
|
||||
@Override
|
||||
public void onServiceStateChanged(@Nullable ServiceState serviceState) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.shadows.ShadowNetworkInfo;
|
||||
|
||||
@ -45,7 +46,7 @@ import org.robolectric.shadows.ShadowNetworkInfo;
|
||||
public final class DefaultBandwidthMeterTest {
|
||||
|
||||
private static final int SIMULATED_TRANSFER_COUNT = 100;
|
||||
private static final String FAST_COUNTRY_ISO = "EE";
|
||||
private static final String FAST_COUNTRY_ISO = "TW";
|
||||
private static final String SLOW_COUNTRY_ISO = "PG";
|
||||
|
||||
private TelephonyManager telephonyManager;
|
||||
@ -55,6 +56,9 @@ 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 Robolectric's
|
||||
// ShadowTelephonyManager doesn't handle requests to return the ServiceState.
|
||||
private NetworkInfo networkInfo5gSa;
|
||||
private NetworkInfo networkInfoEthernet;
|
||||
|
||||
@Before
|
||||
@ -103,6 +107,13 @@ public final class DefaultBandwidthMeterTest {
|
||||
TelephonyManager.NETWORK_TYPE_LTE,
|
||||
/* isAvailable= */ true,
|
||||
CONNECTED);
|
||||
networkInfo5gSa =
|
||||
ShadowNetworkInfo.newInstance(
|
||||
DetailedState.CONNECTED,
|
||||
ConnectivityManager.TYPE_MOBILE,
|
||||
TelephonyManager.NETWORK_TYPE_NR,
|
||||
/* isAvailable= */ true,
|
||||
CONNECTED);
|
||||
networkInfoEthernet =
|
||||
ShadowNetworkInfo.newInstance(
|
||||
DetailedState.CONNECTED,
|
||||
@ -217,6 +228,22 @@ public final class DefaultBandwidthMeterTest {
|
||||
assertThat(initialEstimate3g).isGreaterThan(initialEstimate2g);
|
||||
}
|
||||
|
||||
@Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29
|
||||
@Test
|
||||
public void defaultInitialBitrateEstimate_for5gSa_isGreaterThanEstimateFor4g() {
|
||||
setActiveNetworkInfo(networkInfo4g);
|
||||
DefaultBandwidthMeter bandwidthMeter4g =
|
||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||
long initialEstimate4g = bandwidthMeter4g.getBitrateEstimate();
|
||||
|
||||
setActiveNetworkInfo(networkInfo5gSa);
|
||||
DefaultBandwidthMeter bandwidthMeter5gSa =
|
||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||
long initialEstimate5gSa = bandwidthMeter5gSa.getBitrateEstimate();
|
||||
|
||||
assertThat(initialEstimate5gSa).isGreaterThan(initialEstimate4g);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultInitialBitrateEstimate_forOffline_isReasonable() {
|
||||
setActiveNetworkInfo(networkInfoOffline);
|
||||
@ -313,6 +340,24 @@ public final class DefaultBandwidthMeterTest {
|
||||
assertThat(initialEstimateFast).isGreaterThan(initialEstimateSlow);
|
||||
}
|
||||
|
||||
@Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29
|
||||
@Test
|
||||
public void
|
||||
defaultInitialBitrateEstimate_for5gSa_forFastCountry_isGreaterThanEstimateForSlowCountry() {
|
||||
setActiveNetworkInfo(networkInfo5gSa);
|
||||
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
|
||||
public void initialBitrateEstimateOverwrite_whileConnectedToNetwork_setsInitialEstimate() {
|
||||
setActiveNetworkInfo(networkInfoWifi);
|
||||
@ -463,6 +508,33 @@ public final class DefaultBandwidthMeterTest {
|
||||
assertThat(initialEstimate).isNotEqualTo(123456789);
|
||||
}
|
||||
|
||||
@Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29
|
||||
@Test
|
||||
public void initialBitrateEstimateOverwrite_for5gSa_whileConnectedTo5gSa_setsInitialEstimate() {
|
||||
setActiveNetworkInfo(networkInfo5gSa);
|
||||
DefaultBandwidthMeter bandwidthMeter =
|
||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setInitialBitrateEstimate(C.NETWORK_TYPE_5G_SA, 123456789)
|
||||
.build();
|
||||
long initialEstimate = bandwidthMeter.getBitrateEstimate();
|
||||
|
||||
assertThat(initialEstimate).isEqualTo(123456789);
|
||||
}
|
||||
|
||||
@Config(sdk = Config.NEWEST_SDK) // TODO: Remove once targetSDK >= 29
|
||||
@Test
|
||||
public void
|
||||
initialBitrateEstimateOverwrite_for5gSa_whileConnectedToOtherNetwork_doesNotSetInitialEstimate() {
|
||||
setActiveNetworkInfo(networkInfoWifi);
|
||||
DefaultBandwidthMeter bandwidthMeter =
|
||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setInitialBitrateEstimate(C.NETWORK_TYPE_5G_SA, 123456789)
|
||||
.build();
|
||||
long initialEstimate = bandwidthMeter.getBitrateEstimate();
|
||||
|
||||
assertThat(initialEstimate).isNotEqualTo(123456789);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialBitrateEstimateOverwrite_forOffline_whileOffline_setsInitialEstimate() {
|
||||
setActiveNetworkInfo(networkInfoOffline);
|
||||
|
Loading…
x
Reference in New Issue
Block a user