mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add missing synchronization in ExperimentalBandwidthMeter
Issue: androidx/media#612 PiperOrigin-RevId: 563690229
This commit is contained in:
parent
f2b1d0cfa3
commit
dd2a373636
5 changed files with 134 additions and 22 deletions
|
|
@ -14,6 +14,8 @@
|
||||||
([#8699](https://github.com/google/ExoPlayer/issues/8699)).
|
([#8699](https://github.com/google/ExoPlayer/issues/8699)).
|
||||||
* Add functionality to transmit Common Media Client Data (CMCD) data using
|
* Add functionality to transmit Common Media Client Data (CMCD) data using
|
||||||
query parameters ([#553](https://github.com/androidx/media/issues/553)).
|
query parameters ([#553](https://github.com/androidx/media/issues/553)).
|
||||||
|
* Fix `ConcurrentModificationException` in `ExperimentalBandwidthMeter`
|
||||||
|
([#612](https://github.com/androidx/media/issues/612)).
|
||||||
* Transformer:
|
* Transformer:
|
||||||
* Changed `frameRate` and `durationUs` parameters of
|
* Changed `frameRate` and `durationUs` parameters of
|
||||||
`SampleConsumer.queueInputBitmap` to `TimestampIterator`.
|
`SampleConsumer.queueInputBitmap` to `TimestampIterator`.
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.upstream;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Assertions;
|
import androidx.media3.common.util.Assertions;
|
||||||
|
|
@ -285,20 +286,34 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
||||||
|
|
||||||
private final ImmutableMap<Integer, Long> initialBitrateEstimates;
|
private final ImmutableMap<Integer, Long> initialBitrateEstimates;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final SlidingPercentile slidingPercentile;
|
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final boolean resetOnNetworkTypeChange;
|
private final boolean resetOnNetworkTypeChange;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
|
private final SlidingPercentile slidingPercentile;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private int streamCount;
|
private int streamCount;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long sampleStartTimeMs;
|
private long sampleStartTimeMs;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long sampleBytesTransferred;
|
private long sampleBytesTransferred;
|
||||||
|
|
||||||
private @C.NetworkType int networkType;
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long totalElapsedTimeMs;
|
private long totalElapsedTimeMs;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long totalBytesTransferred;
|
private long totalBytesTransferred;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long bitrateEstimate;
|
private long bitrateEstimate;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
private long lastReportedBitrateEstimate;
|
private long lastReportedBitrateEstimate;
|
||||||
|
|
||||||
|
private @C.NetworkType int networkType;
|
||||||
private boolean networkTypeOverrideSet;
|
private boolean networkTypeOverrideSet;
|
||||||
private @C.NetworkType int networkTypeOverride;
|
private @C.NetworkType int networkTypeOverride;
|
||||||
|
|
||||||
|
|
@ -445,6 +460,7 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
||||||
slidingPercentile.reset();
|
slidingPercentile.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("this")
|
||||||
private void maybeNotifyBandwidthSample(
|
private void maybeNotifyBandwidthSample(
|
||||||
int elapsedMs, long bytesTransferred, long bitrateEstimate) {
|
int elapsedMs, long bytesTransferred, long bitrateEstimate) {
|
||||||
if (elapsedMs == 0 && bytesTransferred == 0 && bitrateEstimate == lastReportedBitrateEstimate) {
|
if (elapsedMs == 0 && bytesTransferred == 0 && bitrateEstimate == lastReportedBitrateEstimate) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.NetworkTypeObserver;
|
import androidx.media3.common.util.NetworkTypeObserver;
|
||||||
|
|
@ -275,10 +276,14 @@ public final class ExperimentalBandwidthMeter implements BandwidthMeter, Transfe
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmutableMap<Integer, Long> initialBitrateEstimates;
|
private final ImmutableMap<Integer, Long> initialBitrateEstimates;
|
||||||
private final TimeToFirstByteEstimator timeToFirstByteEstimator;
|
|
||||||
private final BandwidthEstimator bandwidthEstimator;
|
|
||||||
private final boolean resetOnNetworkTypeChange;
|
private final boolean resetOnNetworkTypeChange;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
|
private final TimeToFirstByteEstimator timeToFirstByteEstimator;
|
||||||
|
|
||||||
|
@GuardedBy("this") // Used in TransferListener methods that are called on a background thread.
|
||||||
|
private final BandwidthEstimator bandwidthEstimator;
|
||||||
|
|
||||||
private @C.NetworkType int networkType;
|
private @C.NetworkType int networkType;
|
||||||
private long initialBitrateEstimate;
|
private long initialBitrateEstimate;
|
||||||
private boolean networkTypeOverrideSet;
|
private boolean networkTypeOverrideSet;
|
||||||
|
|
@ -323,7 +328,7 @@ public final class ExperimentalBandwidthMeter implements BandwidthMeter, Transfe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeToFirstByteEstimateUs() {
|
public synchronized long getTimeToFirstByteEstimateUs() {
|
||||||
return timeToFirstByteEstimator.getTimeToFirstByteEstimateUs();
|
return timeToFirstByteEstimator.getTimeToFirstByteEstimateUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,19 +338,20 @@ public final class ExperimentalBandwidthMeter implements BandwidthMeter, Transfe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addEventListener(Handler eventHandler, EventListener eventListener) {
|
public synchronized void addEventListener(Handler eventHandler, EventListener eventListener) {
|
||||||
checkNotNull(eventHandler);
|
checkNotNull(eventHandler);
|
||||||
checkNotNull(eventListener);
|
checkNotNull(eventListener);
|
||||||
bandwidthEstimator.addEventListener(eventHandler, eventListener);
|
bandwidthEstimator.addEventListener(eventHandler, eventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeEventListener(EventListener eventListener) {
|
public synchronized void removeEventListener(EventListener eventListener) {
|
||||||
bandwidthEstimator.removeEventListener(eventListener);
|
bandwidthEstimator.removeEventListener(eventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTransferInitializing(DataSource source, DataSpec dataSpec, boolean isNetwork) {
|
public synchronized void onTransferInitializing(
|
||||||
|
DataSource source, DataSpec dataSpec, boolean isNetwork) {
|
||||||
if (!isTransferAtFullNetworkSpeed(dataSpec, isNetwork)) {
|
if (!isTransferAtFullNetworkSpeed(dataSpec, isNetwork)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,6 @@ import org.robolectric.shadows.ShadowTelephonyManager;
|
||||||
@Config(sdk = Config.ALL_SDKS) // Test all SDKs because network detection logic changed over time.
|
@Config(sdk = Config.ALL_SDKS) // Test all SDKs because network detection logic changed over time.
|
||||||
public final class DefaultBandwidthMeterTest {
|
public final class DefaultBandwidthMeterTest {
|
||||||
|
|
||||||
private static final int SIMULATED_TRANSFER_COUNT = 100;
|
|
||||||
private static final String FAST_COUNTRY_ISO = "TW";
|
private static final String FAST_COUNTRY_ISO = "TW";
|
||||||
private static final String SLOW_COUNTRY_ISO = "PG";
|
private static final String SLOW_COUNTRY_ISO = "PG";
|
||||||
|
|
||||||
|
|
@ -668,7 +667,8 @@ public final class DefaultBandwidthMeterTest {
|
||||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.setClock(clock)
|
.setClock(clock)
|
||||||
.build();
|
.build();
|
||||||
long[] bitrateEstimatesWithNewInstance = simulateTransfers(bandwidthMeter, clock);
|
long[] bitrateEstimatesWithNewInstance =
|
||||||
|
simulateTransfers(bandwidthMeter, clock, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// Create a new instance and seed with some transfers.
|
// Create a new instance and seed with some transfers.
|
||||||
setActiveNetworkInfo(networkInfo2g);
|
setActiveNetworkInfo(networkInfo2g);
|
||||||
|
|
@ -676,11 +676,12 @@ public final class DefaultBandwidthMeterTest {
|
||||||
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.setClock(clock)
|
.setClock(clock)
|
||||||
.build();
|
.build();
|
||||||
simulateTransfers(bandwidthMeter, clock);
|
simulateTransfers(bandwidthMeter, clock, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// Override the network type to ethernet and simulate transfers again.
|
// Override the network type to ethernet and simulate transfers again.
|
||||||
bandwidthMeter.setNetworkTypeOverride(C.NETWORK_TYPE_ETHERNET);
|
bandwidthMeter.setNetworkTypeOverride(C.NETWORK_TYPE_ETHERNET);
|
||||||
long[] bitrateEstimatesAfterReset = simulateTransfers(bandwidthMeter, clock);
|
long[] bitrateEstimatesAfterReset =
|
||||||
|
simulateTransfers(bandwidthMeter, clock, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// If overriding the network type fully reset the bandwidth meter, we expect the bitrate
|
// If overriding the network type fully reset the bandwidth meter, we expect the bitrate
|
||||||
// estimates generated during simulation to be the same.
|
// estimates generated during simulation to be the same.
|
||||||
|
|
@ -697,6 +698,36 @@ public final class DefaultBandwidthMeterTest {
|
||||||
assertThat(initialEstimate).isLessThan(50_000_000L);
|
assertThat(initialEstimate).isLessThan(50_000_000L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBitrateEstimate_withSimultaneousTransferEvents_receivesUpdatedValues() {
|
||||||
|
FakeClock clock = new FakeClock(/* initialTimeMs= */ 0);
|
||||||
|
DefaultBandwidthMeter bandwidthMeter =
|
||||||
|
new DefaultBandwidthMeter.Builder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setClock(clock)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Thread thread =
|
||||||
|
new Thread("backgroundTransfers") {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
simulateTransfers(bandwidthMeter, clock, /* simulatedTransferCount= */ 10000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
long currentBitrateEstimate = bandwidthMeter.getBitrateEstimate();
|
||||||
|
boolean bitrateEstimateUpdated = false;
|
||||||
|
while (thread.isAlive()) {
|
||||||
|
long newBitrateEstimate = bandwidthMeter.getBitrateEstimate();
|
||||||
|
if (newBitrateEstimate != currentBitrateEstimate) {
|
||||||
|
currentBitrateEstimate = newBitrateEstimate;
|
||||||
|
bitrateEstimateUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(bitrateEstimateUpdated).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private void setActiveNetworkInfo(NetworkInfo networkInfo) {
|
private void setActiveNetworkInfo(NetworkInfo networkInfo) {
|
||||||
setActiveNetworkInfo(networkInfo, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
|
setActiveNetworkInfo(networkInfo, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
|
||||||
}
|
}
|
||||||
|
|
@ -725,12 +756,13 @@ public final class DefaultBandwidthMeterTest {
|
||||||
Shadows.shadowOf(telephonyManager).setNetworkCountryIso(countryIso);
|
Shadows.shadowOf(telephonyManager).setNetworkCountryIso(countryIso);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long[] simulateTransfers(DefaultBandwidthMeter bandwidthMeter, FakeClock clock) {
|
private static long[] simulateTransfers(
|
||||||
long[] bitrateEstimates = new long[SIMULATED_TRANSFER_COUNT];
|
DefaultBandwidthMeter bandwidthMeter, FakeClock clock, int simulatedTransferCount) {
|
||||||
|
long[] bitrateEstimates = new long[simulatedTransferCount];
|
||||||
Random random = new Random(/* seed= */ 0);
|
Random random = new Random(/* seed= */ 0);
|
||||||
DataSource dataSource = new FakeDataSource();
|
DataSource dataSource = new FakeDataSource();
|
||||||
DataSpec dataSpec = new DataSpec(Uri.parse("https://test.com"));
|
DataSpec dataSpec = new DataSpec(Uri.parse("https://test.com"));
|
||||||
for (int i = 0; i < SIMULATED_TRANSFER_COUNT; i++) {
|
for (int i = 0; i < simulatedTransferCount; i++) {
|
||||||
bandwidthMeter.onTransferStart(dataSource, dataSpec, /* isNetwork= */ true);
|
bandwidthMeter.onTransferStart(dataSource, dataSpec, /* isNetwork= */ true);
|
||||||
clock.advanceTime(random.nextInt(/* bound= */ 5000));
|
clock.advanceTime(random.nextInt(/* bound= */ 5000));
|
||||||
bandwidthMeter.onBytesTransferred(
|
bandwidthMeter.onBytesTransferred(
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ import org.robolectric.shadows.ShadowTelephonyManager;
|
||||||
@Config(sdk = Config.ALL_SDKS) // Test all SDKs because network detection logic changed over time.
|
@Config(sdk = Config.ALL_SDKS) // Test all SDKs because network detection logic changed over time.
|
||||||
public final class ExperimentalBandwidthMeterTest {
|
public final class ExperimentalBandwidthMeterTest {
|
||||||
|
|
||||||
private static final int SIMULATED_TRANSFER_COUNT = 100;
|
|
||||||
private static final String FAST_COUNTRY_ISO = "TW";
|
private static final String FAST_COUNTRY_ISO = "TW";
|
||||||
private static final String SLOW_COUNTRY_ISO = "PG";
|
private static final String SLOW_COUNTRY_ISO = "PG";
|
||||||
|
|
||||||
|
|
@ -666,23 +665,79 @@ public final class ExperimentalBandwidthMeterTest {
|
||||||
setActiveNetworkInfo(networkInfoEthernet);
|
setActiveNetworkInfo(networkInfoEthernet);
|
||||||
ExperimentalBandwidthMeter bandwidthMeter =
|
ExperimentalBandwidthMeter bandwidthMeter =
|
||||||
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||||
long[] bitrateEstimatesWithNewInstance = simulateTransfers(bandwidthMeter);
|
long[] bitrateEstimatesWithNewInstance =
|
||||||
|
simulateTransfers(bandwidthMeter, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// Create a new instance and seed with some transfers.
|
// Create a new instance and seed with some transfers.
|
||||||
setActiveNetworkInfo(networkInfo2g);
|
setActiveNetworkInfo(networkInfo2g);
|
||||||
bandwidthMeter =
|
bandwidthMeter =
|
||||||
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||||
simulateTransfers(bandwidthMeter);
|
simulateTransfers(bandwidthMeter, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// Override the network type to ethernet and simulate transfers again.
|
// Override the network type to ethernet and simulate transfers again.
|
||||||
bandwidthMeter.setNetworkTypeOverride(C.NETWORK_TYPE_ETHERNET);
|
bandwidthMeter.setNetworkTypeOverride(C.NETWORK_TYPE_ETHERNET);
|
||||||
long[] bitrateEstimatesAfterReset = simulateTransfers(bandwidthMeter);
|
long[] bitrateEstimatesAfterReset =
|
||||||
|
simulateTransfers(bandwidthMeter, /* simulatedTransferCount= */ 100);
|
||||||
|
|
||||||
// If overriding the network type fully reset the bandwidth meter, we expect the bitrate
|
// If overriding the network type fully reset the bandwidth meter, we expect the bitrate
|
||||||
// estimates generated during simulation to be the same.
|
// estimates generated during simulation to be the same.
|
||||||
assertThat(bitrateEstimatesAfterReset).isEqualTo(bitrateEstimatesWithNewInstance);
|
assertThat(bitrateEstimatesAfterReset).isEqualTo(bitrateEstimatesWithNewInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getTimeToFirstByteEstimateUs_withSimultaneousTransferEvents_receivesUpdatedValues() {
|
||||||
|
ExperimentalBandwidthMeter bandwidthMeter =
|
||||||
|
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||||
|
|
||||||
|
Thread thread =
|
||||||
|
new Thread("backgroundTransfers") {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
simulateTransfers(bandwidthMeter, /* simulatedTransferCount= */ 10000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
long currentTimeToFirstByteEstimateUs = bandwidthMeter.getTimeToFirstByteEstimateUs();
|
||||||
|
boolean timeToFirstByteEstimateUpdated = false;
|
||||||
|
while (thread.isAlive()) {
|
||||||
|
long newTimeToFirstByteEstimateUs = bandwidthMeter.getTimeToFirstByteEstimateUs();
|
||||||
|
if (newTimeToFirstByteEstimateUs != currentTimeToFirstByteEstimateUs) {
|
||||||
|
currentTimeToFirstByteEstimateUs = newTimeToFirstByteEstimateUs;
|
||||||
|
timeToFirstByteEstimateUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(timeToFirstByteEstimateUpdated).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getBitrateEstimate_withSimultaneousTransferEvents_receivesUpdatedValues() {
|
||||||
|
ExperimentalBandwidthMeter bandwidthMeter =
|
||||||
|
new ExperimentalBandwidthMeter.Builder(ApplicationProvider.getApplicationContext()).build();
|
||||||
|
|
||||||
|
Thread thread =
|
||||||
|
new Thread("backgroundTransfers") {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
simulateTransfers(bandwidthMeter, /* simulatedTransferCount= */ 10000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
long currentBitrateEstimate = bandwidthMeter.getBitrateEstimate();
|
||||||
|
boolean bitrateEstimateUpdated = false;
|
||||||
|
while (thread.isAlive()) {
|
||||||
|
long newBitrateEstimate = bandwidthMeter.getBitrateEstimate();
|
||||||
|
if (newBitrateEstimate != currentBitrateEstimate) {
|
||||||
|
currentBitrateEstimate = newBitrateEstimate;
|
||||||
|
bitrateEstimateUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(bitrateEstimateUpdated).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private void setActiveNetworkInfo(NetworkInfo networkInfo) {
|
private void setActiveNetworkInfo(NetworkInfo networkInfo) {
|
||||||
setActiveNetworkInfo(networkInfo, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
|
setActiveNetworkInfo(networkInfo, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
|
||||||
}
|
}
|
||||||
|
|
@ -711,12 +766,13 @@ public final class ExperimentalBandwidthMeterTest {
|
||||||
Shadows.shadowOf(telephonyManager).setNetworkCountryIso(countryIso);
|
Shadows.shadowOf(telephonyManager).setNetworkCountryIso(countryIso);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long[] simulateTransfers(ExperimentalBandwidthMeter bandwidthMeter) {
|
private static long[] simulateTransfers(
|
||||||
long[] bitrateEstimates = new long[SIMULATED_TRANSFER_COUNT];
|
ExperimentalBandwidthMeter bandwidthMeter, int simulatedTransferCount) {
|
||||||
|
long[] bitrateEstimates = new long[simulatedTransferCount];
|
||||||
Random random = new Random(/* seed= */ 0);
|
Random random = new Random(/* seed= */ 0);
|
||||||
DataSource dataSource = new FakeDataSource();
|
DataSource dataSource = new FakeDataSource();
|
||||||
DataSpec dataSpec = new DataSpec(Uri.parse("https://test.com"));
|
DataSpec dataSpec = new DataSpec(Uri.parse("https://test.com"));
|
||||||
for (int i = 0; i < SIMULATED_TRANSFER_COUNT; i++) {
|
for (int i = 0; i < simulatedTransferCount; i++) {
|
||||||
bandwidthMeter.onTransferInitializing(dataSource, dataSpec, /* isNetwork= */ true);
|
bandwidthMeter.onTransferInitializing(dataSource, dataSpec, /* isNetwork= */ true);
|
||||||
ShadowSystemClock.advanceBy(Duration.ofMillis(random.nextInt(50)));
|
ShadowSystemClock.advanceBy(Duration.ofMillis(random.nextInt(50)));
|
||||||
bandwidthMeter.onTransferStart(dataSource, dataSpec, /* isNetwork= */ true);
|
bandwidthMeter.onTransferStart(dataSource, dataSpec, /* isNetwork= */ true);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue