From f77e96bca8ca43746ab67fac3e735fd6b7b4df98 Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 18 Jul 2017 01:47:59 -0700 Subject: [PATCH] Allow to extend FakeDataSource. Extensions can perform additional actions whenever data is read (e.g. sleeping to simulate bandwidth restrictions). Additionally, the factory class can also be overwritten and allows to set the FakeDataSet later in case it is not available right away. Moreover, this class now also uses a transfer listener similar to all real data sources. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=162326000 --- .../exoplayer2/testutil/FakeDataSet.java | 7 +- .../exoplayer2/testutil/FakeDataSource.java | 74 ++++++++++++++----- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java index 988ee69497..2580205361 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSet.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.testutil; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.util.Assertions; @@ -77,11 +78,11 @@ public class FakeDataSet { */ public static final class Segment { - public final IOException exception; - public final byte[] data; + public @Nullable final IOException exception; + public @Nullable final byte[] data; public final int length; public final long byteOffset; - public final Runnable action; + public @Nullable final Runnable action; public boolean exceptionThrown; public boolean exceptionCleared; diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java index 3f01292523..6180a8aa77 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeDataSource.java @@ -16,12 +16,14 @@ package com.google.android.exoplayer2.testutil; import android.net.Uri; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData; import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSourceException; import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; import java.util.ArrayList; @@ -30,9 +32,34 @@ import java.util.ArrayList; * A fake {@link DataSource} capable of simulating various scenarios. It uses a {@link FakeDataSet} * instance which determines the response to data access calls. */ -public final class FakeDataSource implements DataSource { +public class FakeDataSource implements DataSource { + + /** + * Factory to create a {@link FakeDataSource}. + */ + public static class Factory implements DataSource.Factory { + + protected final TransferListener transferListener; + protected FakeDataSet fakeDataSet; + + public Factory(@Nullable TransferListener transferListener) { + this.transferListener = transferListener; + } + + public final Factory setFakeDataSet(FakeDataSet fakeDataSet) { + this.fakeDataSet = fakeDataSet; + return this; + } + + @Override + public DataSource createDataSource() { + return new FakeDataSource(fakeDataSet, transferListener); + } + + } private final FakeDataSet fakeDataSet; + private final TransferListener transferListener; private final ArrayList openedDataSpecs; private Uri uri; @@ -41,30 +68,28 @@ public final class FakeDataSource implements DataSource { private int currentSegmentIndex; private long bytesRemaining; - public static Factory newFactory(final FakeDataSet fakeDataSet) { - return new Factory() { - @Override - public DataSource createDataSource() { - return new FakeDataSource(fakeDataSet); - } - }; - } - public FakeDataSource() { this(new FakeDataSet()); } public FakeDataSource(FakeDataSet fakeDataSet) { + this(fakeDataSet, null); + } + + public FakeDataSource(FakeDataSet fakeDataSet, + @Nullable TransferListener transferListener) { + Assertions.checkNotNull(fakeDataSet); this.fakeDataSet = fakeDataSet; + this.transferListener = transferListener; this.openedDataSpecs = new ArrayList<>(); } - public FakeDataSet getDataSet() { + public final FakeDataSet getDataSet() { return fakeDataSet; } @Override - public long open(DataSpec dataSpec) throws IOException { + public final long open(DataSpec dataSpec) throws IOException { Assertions.checkState(!opened); // DataSpec requires a matching close call even if open fails. opened = true; @@ -104,6 +129,9 @@ public final class FakeDataSource implements DataSource { currentSegmentIndex++; } } + if (transferListener != null) { + transferListener.onTransferStart(this, dataSpec); + } // Configure bytesRemaining, and return. if (dataSpec.length == C.LENGTH_UNSET) { bytesRemaining = totalLength - dataSpec.position; @@ -115,7 +143,7 @@ public final class FakeDataSource implements DataSource { } @Override - public int read(byte[] buffer, int offset, int readLength) throws IOException { + public final int read(byte[] buffer, int offset, int readLength) throws IOException { Assertions.checkState(opened); while (true) { if (currentSegmentIndex == fakeData.getSegments().size() || bytesRemaining == 0) { @@ -138,7 +166,13 @@ public final class FakeDataSource implements DataSource { // Do not allow crossing of the segment boundary. readLength = Math.min(readLength, current.length - current.bytesRead); // Perform the read and return. - System.arraycopy(current.data, current.bytesRead, buffer, offset, readLength); + if (current.data != null) { + System.arraycopy(current.data, current.bytesRead, buffer, offset, readLength); + } + onDataRead(readLength); + if (transferListener != null) { + transferListener.onBytesTransferred(this, readLength); + } bytesRemaining -= readLength; current.bytesRead += readLength; if (current.bytesRead == current.length) { @@ -150,12 +184,12 @@ public final class FakeDataSource implements DataSource { } @Override - public Uri getUri() { + public final Uri getUri() { return uri; } @Override - public void close() throws IOException { + public final void close() throws IOException { Assertions.checkState(opened); opened = false; uri = null; @@ -165,6 +199,9 @@ public final class FakeDataSource implements DataSource { current.exceptionCleared = true; } } + if (transferListener != null) { + transferListener.onTransferEnd(this); + } fakeData = null; } @@ -172,12 +209,15 @@ public final class FakeDataSource implements DataSource { * Returns the {@link DataSpec} instances passed to {@link #open(DataSpec)} since the last call to * this method. */ - public DataSpec[] getAndClearOpenedDataSpecs() { + public final DataSpec[] getAndClearOpenedDataSpecs() { DataSpec[] dataSpecs = new DataSpec[openedDataSpecs.size()]; openedDataSpecs.toArray(dataSpecs); openedDataSpecs.clear(); return dataSpecs; } + protected void onDataRead(int bytesRead) { + // Do nothing. Can be overridden. + } }