mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Move Util.getNetworkType into NetworkTypeObserver.
The main user of the Util method is the bandwidth meter to set the initial network type. If this is the first call to the NetworkTypeObserver, then we should also allow the first update to a known network type even if no reset on network type is activated. The other uses are analytics listeners that check the network type at certain events. This can just use the lookup method of the NetworkTypeObserver. PiperOrigin-RevId: 363670771
This commit is contained in:
parent
1affbf9357
commit
f8727b5e87
4 changed files with 128 additions and 102 deletions
|
|
@ -37,8 +37,6 @@ import android.database.DatabaseUtils;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Point;
|
||||
import android.media.AudioFormat;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
|
|
@ -2148,52 +2146,6 @@ public final class Util {
|
|||
return buffer.order() == ByteOrder.BIG_ENDIAN ? value : Integer.reverseBytes(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link C.NetworkType} of the current network connection.
|
||||
*
|
||||
* @param context A context to access the connectivity manager.
|
||||
* @return The {@link C.NetworkType} of the current network connection.
|
||||
*/
|
||||
// Intentional null check to guard against user input.
|
||||
@SuppressWarnings("known.nonnull")
|
||||
@C.NetworkType
|
||||
public static int getNetworkType(Context context) {
|
||||
if (context == null) {
|
||||
// Note: This is for backward compatibility only (context used to be @Nullable).
|
||||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
NetworkInfo networkInfo;
|
||||
@Nullable
|
||||
ConnectivityManager connectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivityManager == null) {
|
||||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
try {
|
||||
networkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
} catch (SecurityException e) {
|
||||
// Expected if permission was revoked.
|
||||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
if (networkInfo == null || !networkInfo.isConnected()) {
|
||||
return C.NETWORK_TYPE_OFFLINE;
|
||||
}
|
||||
switch (networkInfo.getType()) {
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
return C.NETWORK_TYPE_WIFI;
|
||||
case ConnectivityManager.TYPE_WIMAX:
|
||||
return C.NETWORK_TYPE_4G;
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
case ConnectivityManager.TYPE_MOBILE_DUN:
|
||||
case ConnectivityManager.TYPE_MOBILE_HIPRI:
|
||||
return getMobileNetworkType(networkInfo);
|
||||
case ConnectivityManager.TYPE_ETHERNET:
|
||||
return C.NETWORK_TYPE_ETHERNET;
|
||||
default:
|
||||
return C.NETWORK_TYPE_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the upper-case ISO 3166-1 alpha-2 country code of the current registered operator's MCC
|
||||
* (Mobile Country Code), or the country code of the default Locale if not available.
|
||||
|
|
@ -2482,38 +2434,6 @@ public final class Util {
|
|||
return locale.toLanguageTag();
|
||||
}
|
||||
|
||||
private static @C.NetworkType int getMobileNetworkType(NetworkInfo networkInfo) {
|
||||
switch (networkInfo.getSubtype()) {
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
return C.NETWORK_TYPE_2G;
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
|
||||
return C.NETWORK_TYPE_3G;
|
||||
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||
return C.NETWORK_TYPE_4G;
|
||||
case TelephonyManager.NETWORK_TYPE_NR:
|
||||
return SDK_INT >= 29 ? C.NETWORK_TYPE_5G : C.NETWORK_TYPE_UNKNOWN;
|
||||
case TelephonyManager.NETWORK_TYPE_IWLAN:
|
||||
return C.NETWORK_TYPE_WIFI;
|
||||
case TelephonyManager.NETWORK_TYPE_GSM:
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
default: // Future mobile network types.
|
||||
return C.NETWORK_TYPE_CELLULAR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private static HashMap<String, String> createIsoLanguageReplacementMap() {
|
||||
String[] iso2Languages = Locale.getISOLanguages();
|
||||
HashMap<String, String> replacedLanguages =
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
private final EventDispatcher eventDispatcher;
|
||||
private final SlidingPercentile slidingPercentile;
|
||||
private final Clock clock;
|
||||
private final boolean resetOnNetworkTypeChange;
|
||||
|
||||
private int streamCount;
|
||||
private long sampleStartTimeMs;
|
||||
|
|
@ -294,13 +295,15 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
this.eventDispatcher = new EventDispatcher();
|
||||
this.slidingPercentile = new SlidingPercentile(maxWeight);
|
||||
this.clock = clock;
|
||||
// Set the initial network type and bitrate estimate
|
||||
networkType = context == null ? C.NETWORK_TYPE_UNKNOWN : Util.getNetworkType(context);
|
||||
bitrateEstimate = getInitialBitrateEstimateForNetworkType(networkType);
|
||||
// Register to receive network change information if possible.
|
||||
if (context != null && resetOnNetworkTypeChange) {
|
||||
this.resetOnNetworkTypeChange = resetOnNetworkTypeChange;
|
||||
if (context != null) {
|
||||
NetworkTypeObserver networkTypeObserver = NetworkTypeObserver.getInstance(context);
|
||||
networkType = networkTypeObserver.getNetworkType();
|
||||
bitrateEstimate = getInitialBitrateEstimateForNetworkType(networkType);
|
||||
networkTypeObserver.register(/* listener= */ this::onNetworkTypeChanged);
|
||||
} else {
|
||||
networkType = C.NETWORK_TYPE_UNKNOWN;
|
||||
bitrateEstimate = getInitialBitrateEstimateForNetworkType(C.NETWORK_TYPE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +394,11 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
}
|
||||
|
||||
private synchronized void onNetworkTypeChanged(@C.NetworkType int networkType) {
|
||||
if (this.networkType != C.NETWORK_TYPE_UNKNOWN && !resetOnNetworkTypeChange) {
|
||||
// Reset on network change disabled. Ignore all updates except the initial one.
|
||||
return;
|
||||
}
|
||||
|
||||
if (networkTypeOverrideSet) {
|
||||
networkType = networkTypeOverride;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,13 +20,16 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.telephony.TelephonyManager;
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/**
|
||||
* Observer for network type changes.
|
||||
|
|
@ -49,12 +52,16 @@ public final class NetworkTypeObserver {
|
|||
void onNetworkTypeChanged(@C.NetworkType int networkType);
|
||||
}
|
||||
|
||||
private static @MonotonicNonNull NetworkTypeObserver staticInstance;
|
||||
@Nullable private static NetworkTypeObserver staticInstance;
|
||||
|
||||
private final Context context;
|
||||
private final Handler mainHandler;
|
||||
// This class needs to hold weak references as it doesn't require listeners to unregister.
|
||||
private final CopyOnWriteArrayList<WeakReference<Listener>> listeners;
|
||||
private final Object networkTypeLock;
|
||||
|
||||
@GuardedBy("networkTypeLock")
|
||||
@C.NetworkType
|
||||
private int networkType;
|
||||
|
||||
/**
|
||||
* Returns a network type observer instance.
|
||||
|
|
@ -68,10 +75,17 @@ public final class NetworkTypeObserver {
|
|||
return staticInstance;
|
||||
}
|
||||
|
||||
/** Resets the network type observer for tests. */
|
||||
@VisibleForTesting
|
||||
public static synchronized void resetForTests() {
|
||||
staticInstance = null;
|
||||
}
|
||||
|
||||
private NetworkTypeObserver(Context context) {
|
||||
this.context = context.getApplicationContext();
|
||||
mainHandler = new Handler(Looper.getMainLooper());
|
||||
listeners = new CopyOnWriteArrayList<>();
|
||||
networkTypeLock = new Object();
|
||||
networkType = C.NETWORK_TYPE_UNKNOWN;
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
context.registerReceiver(/* receiver= */ new Receiver(), filter);
|
||||
|
|
@ -95,7 +109,9 @@ public final class NetworkTypeObserver {
|
|||
/** Returns the current network type. */
|
||||
@C.NetworkType
|
||||
public int getNetworkType() {
|
||||
return Util.getNetworkType(context);
|
||||
synchronized (networkTypeLock) {
|
||||
return networkType;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeClearedReferences() {
|
||||
|
|
@ -106,22 +122,96 @@ public final class NetworkTypeObserver {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateNetworkType(@C.NetworkType int networkType) {
|
||||
synchronized (networkTypeLock) {
|
||||
if (this.networkType == networkType) {
|
||||
return;
|
||||
}
|
||||
this.networkType = networkType;
|
||||
}
|
||||
for (WeakReference<Listener> listenerReference : listeners) {
|
||||
@Nullable Listener listener = listenerReference.get();
|
||||
if (listener != null) {
|
||||
listener.onNetworkTypeChanged(networkType);
|
||||
} else {
|
||||
listeners.remove(listenerReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@C.NetworkType
|
||||
private static int getNetworkTypeFromConnectivityManager(Context context) {
|
||||
NetworkInfo networkInfo;
|
||||
@Nullable
|
||||
ConnectivityManager connectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivityManager == null) {
|
||||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
try {
|
||||
networkInfo = connectivityManager.getActiveNetworkInfo();
|
||||
} catch (SecurityException e) {
|
||||
// Expected if permission was revoked.
|
||||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
if (networkInfo == null || !networkInfo.isConnected()) {
|
||||
return C.NETWORK_TYPE_OFFLINE;
|
||||
}
|
||||
switch (networkInfo.getType()) {
|
||||
case ConnectivityManager.TYPE_WIFI:
|
||||
return C.NETWORK_TYPE_WIFI;
|
||||
case ConnectivityManager.TYPE_WIMAX:
|
||||
return C.NETWORK_TYPE_4G;
|
||||
case ConnectivityManager.TYPE_MOBILE:
|
||||
case ConnectivityManager.TYPE_MOBILE_DUN:
|
||||
case ConnectivityManager.TYPE_MOBILE_HIPRI:
|
||||
return getMobileNetworkType(networkInfo);
|
||||
case ConnectivityManager.TYPE_ETHERNET:
|
||||
return C.NETWORK_TYPE_ETHERNET;
|
||||
default:
|
||||
return C.NETWORK_TYPE_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
@C.NetworkType
|
||||
private static int getMobileNetworkType(NetworkInfo networkInfo) {
|
||||
switch (networkInfo.getSubtype()) {
|
||||
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||
return C.NETWORK_TYPE_2G;
|
||||
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_0:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_A:
|
||||
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
|
||||
return C.NETWORK_TYPE_3G;
|
||||
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;
|
||||
case TelephonyManager.NETWORK_TYPE_IWLAN:
|
||||
return C.NETWORK_TYPE_WIFI;
|
||||
case TelephonyManager.NETWORK_TYPE_GSM:
|
||||
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
|
||||
default: // Future mobile network types.
|
||||
return C.NETWORK_TYPE_CELLULAR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private final class Receiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (isInitialStickyBroadcast()) {
|
||||
return;
|
||||
}
|
||||
@C.NetworkType int networkType = getNetworkType();
|
||||
for (WeakReference<Listener> listenerReference : listeners) {
|
||||
@Nullable Listener listener = listenerReference.get();
|
||||
if (listener != null) {
|
||||
listener.onNetworkTypeChanged(networkType);
|
||||
} else {
|
||||
listeners.remove(listenerReference);
|
||||
}
|
||||
}
|
||||
@C.NetworkType int networkType = getNetworkTypeFromConnectivityManager(context);
|
||||
updateNetworkType(networkType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import static android.net.NetworkInfo.State.DISCONNECTED;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
|
|
@ -30,11 +31,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.testutil.FakeClock;
|
||||
import com.google.android.exoplayer2.testutil.FakeDataSource;
|
||||
import com.google.android.exoplayer2.util.NetworkTypeObserver;
|
||||
import java.util.Random;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.shadows.ShadowNetworkInfo;
|
||||
|
||||
/** Unit test for {@link DefaultBandwidthMeter}. */
|
||||
|
|
@ -56,6 +59,7 @@ public final class DefaultBandwidthMeterTest {
|
|||
|
||||
@Before
|
||||
public void setUp() {
|
||||
NetworkTypeObserver.resetForTests();
|
||||
connectivityManager =
|
||||
(ConnectivityManager)
|
||||
ApplicationProvider.getApplicationContext()
|
||||
|
|
@ -559,8 +563,12 @@ public final class DefaultBandwidthMeterTest {
|
|||
assertThat(initialEstimateWithoutBuilder).isLessThan(50_000_000L);
|
||||
}
|
||||
|
||||
@SuppressWarnings("StickyBroadcast")
|
||||
private void setActiveNetworkInfo(NetworkInfo networkInfo) {
|
||||
Shadows.shadowOf(connectivityManager).setActiveNetworkInfo(networkInfo);
|
||||
ApplicationProvider.getApplicationContext()
|
||||
.sendStickyBroadcast(new Intent(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
ShadowLooper.idleMainLooper();
|
||||
}
|
||||
|
||||
private void setNetworkCountryIso(String countryIso) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue