mirror of
https://github.com/androidx/media.git
synced 2025-05-11 09:39:52 +08:00
Add workaround for slow okhttp InputStream.close() on API levels 19/20.
This commit is contained in:
parent
a22ccf9254
commit
6d8c4dd416
@ -18,6 +18,7 @@ package com.google.android.exoplayer.upstream;
|
|||||||
import com.google.android.exoplayer.C;
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.util.Assertions;
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Predicate;
|
import com.google.android.exoplayer.util.Predicate;
|
||||||
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -226,6 +227,7 @@ public class DefaultHttpDataSource implements HttpDataSource {
|
|||||||
public void close() throws HttpDataSourceException {
|
public void close() throws HttpDataSourceException {
|
||||||
try {
|
try {
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
|
Util.maybeTerminateInputStream(connection, bytesRemaining());
|
||||||
try {
|
try {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -15,12 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer.util;
|
package com.google.android.exoplayer.util;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer.C;
|
||||||
import com.google.android.exoplayer.upstream.DataSource;
|
import com.google.android.exoplayer.upstream.DataSource;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -57,6 +61,8 @@ public final class Util {
|
|||||||
Pattern.compile("^(-)?P(([0-9]*)Y)?(([0-9]*)M)?(([0-9]*)D)?"
|
Pattern.compile("^(-)?P(([0-9]*)Y)?(([0-9]*)M)?(([0-9]*)D)?"
|
||||||
+ "(T(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?)?$");
|
+ "(T(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?)?$");
|
||||||
|
|
||||||
|
private static final long MAX_BYTES_TO_DRAIN = 2048;
|
||||||
|
|
||||||
private Util() {}
|
private Util() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -396,4 +402,48 @@ public final class Util {
|
|||||||
return intArray;
|
return intArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On platform API levels 19 and 20, okhttp's implementation of {@link InputStream#close} can
|
||||||
|
* block for a long time if the stream has a lot of data remaining. Call this method before
|
||||||
|
* closing the input stream to make a best effort to cause the input stream to encounter an
|
||||||
|
* unexpected end of input, working around this issue. On other platform API levels, the method
|
||||||
|
* does nothing.
|
||||||
|
*
|
||||||
|
* @param connection The connection whose {@link InputStream} should be terminated.
|
||||||
|
* @param bytesRemaining The number of bytes remaining to be read from the input stream if its
|
||||||
|
* length is known. {@link C#LENGTH_UNBOUNDED} otherwise.
|
||||||
|
*/
|
||||||
|
public static void maybeTerminateInputStream(HttpURLConnection connection, long bytesRemaining) {
|
||||||
|
if (SDK_INT != 19 && SDK_INT != 20) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
if (bytesRemaining == C.LENGTH_UNBOUNDED) {
|
||||||
|
// If the input stream has already ended, do nothing. The socket may be re-used.
|
||||||
|
if (inputStream.read() == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (bytesRemaining <= MAX_BYTES_TO_DRAIN) {
|
||||||
|
// There isn't much data left. Prefer to allow it to drain, which may allow the socket to be
|
||||||
|
// re-used.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String className = inputStream.getClass().getName();
|
||||||
|
if (className.equals("com.android.okhttp.internal.http.HttpTransport$ChunkedInputStream")
|
||||||
|
|| className.equals(
|
||||||
|
"com.android.okhttp.internal.http.HttpTransport$FixedLengthInputStream")) {
|
||||||
|
Class<?> superclass = inputStream.getClass().getSuperclass();
|
||||||
|
Method unexpectedEndOfInput = superclass.getDeclaredMethod("unexpectedEndOfInput");
|
||||||
|
unexpectedEndOfInput.setAccessible(true);
|
||||||
|
unexpectedEndOfInput.invoke(inputStream);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// The connection didn't ever have an input stream, or it was closed already.
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Something went wrong. The device probably isn't using okhttp.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user