Fix bug in CronetDataSource

This change fixes a bug in CronetDataSource when it makes a Range
request but the server does not support Range requests and returns the
entire resource. Before the fix, the CronetDataSource would read more
bytes than the intended range.

PiperOrigin-RevId: 353614477
This commit is contained in:
christosts 2021-01-25 11:41:30 +00:00 committed by Ian Baker
parent dc7fde1ff7
commit 3b08a792bb
2 changed files with 11 additions and 16 deletions

View File

@ -29,9 +29,7 @@ import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.junit.After; import org.junit.After;
import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/** {@link DataSource} contract tests for {@link CronetDataSource}. */ /** {@link DataSource} contract tests for {@link CronetDataSource}. */
@ -70,16 +68,6 @@ public class CronetDataSourceContractTest extends DataSourceContractTest {
return Uri.parse(httpDataSourceTestEnv.getNonexistentUrl()); return Uri.parse(httpDataSourceTestEnv.getNonexistentUrl());
} }
@Override
@Test
@Ignore
public void dataSpecWithLength_readExpectedRange() {}
@Override
@Test
@Ignore
public void dataSpecWithPositionAndLength_readExpectedRange() {}
/** /**
* An {@link HttpDataSource.Factory} that throws {@link UnsupportedOperationException} on every * An {@link HttpDataSource.Factory} that throws {@link UnsupportedOperationException} on every
* interaction. * interaction.

View File

@ -17,7 +17,6 @@ package com.google.android.exoplayer2.ext.cronet;
import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
@ -37,6 +36,7 @@ import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.primitives.Ints;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException; import java.io.InterruptedIOException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
@ -655,14 +655,21 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
readBuffer.flip(); readBuffer.flip();
Assertions.checkState(readBuffer.hasRemaining()); Assertions.checkState(readBuffer.hasRemaining());
if (bytesToSkip > 0) { if (bytesToSkip > 0) {
int bytesSkipped = (int) min(readBuffer.remaining(), bytesToSkip); int bytesSkipped = (int) Math.min(readBuffer.remaining(), bytesToSkip);
readBuffer.position(readBuffer.position() + bytesSkipped); readBuffer.position(readBuffer.position() + bytesSkipped);
bytesToSkip -= bytesSkipped; bytesToSkip -= bytesSkipped;
} }
} }
} }
int bytesRead = min(readBuffer.remaining(), readLength); // Ensure we read up to bytesRemaining, in case this was a Range request with finite end, but
// the server does not support Range requests and transmitted the entire resource.
int bytesRead =
Ints.min(
bytesRemaining != C.LENGTH_UNSET ? (int) bytesRemaining : Integer.MAX_VALUE,
readBuffer.remaining(),
readLength);
readBuffer.get(buffer, offset, bytesRead); readBuffer.get(buffer, offset, bytesRead);
if (bytesRemaining != C.LENGTH_UNSET) { if (bytesRemaining != C.LENGTH_UNSET) {
@ -1039,7 +1046,7 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
// Copy as much as possible from the src buffer into dst buffer. // Copy as much as possible from the src buffer into dst buffer.
// Returns the number of bytes copied. // Returns the number of bytes copied.
private static int copyByteBuffer(ByteBuffer src, ByteBuffer dst) { private static int copyByteBuffer(ByteBuffer src, ByteBuffer dst) {
int remaining = min(src.remaining(), dst.remaining()); int remaining = Math.min(src.remaining(), dst.remaining());
int limit = src.limit(); int limit = src.limit();
src.limit(src.position() + remaining); src.limit(src.position() + remaining);
dst.put(src); dst.put(src);