Fix some ErrorCode assigning cases.

DefaultHttpDataSource and OkHttpDataSource can share the same error code
assigning logic.

Fixes CronetDataSource's handling of closed connection.

PiperOrigin-RevId: 387791679
This commit is contained in:
claincly 2021-07-30 14:31:30 +01:00 committed by Christos Tsilopoulos
parent df49f90b7f
commit 0bf40f8978
4 changed files with 47 additions and 48 deletions

View File

@ -1126,13 +1126,15 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
if (message != null) { if (message != null) {
if (message.contains("net::ERR_INTERNET_DISCONNECTED")) { if (message.contains("net::ERR_INTERNET_DISCONNECTED")) {
return PlaybackException.ERROR_CODE_IO_NETWORK_UNAVAILABLE; return PlaybackException.ERROR_CODE_IO_NETWORK_UNAVAILABLE;
} else if (message.contains("net::ERR_CONTENT_LENGTH_MISMATCH")
|| message.contains("net::ERR_SOCKET_NOT_CONNECTED")) {
return PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED;
} }
} }
if (occurredWhileOpeningConnection) { if (occurredWhileOpeningConnection) {
return PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED; return PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED;
} else {
return PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED;
} }
return PlaybackException.ERROR_CODE_IO_UNSPECIFIED;
} }
private static boolean isCompressed(UrlResponseInfo info) { private static boolean isCompressed(UrlResponseInfo info) {

View File

@ -33,7 +33,6 @@ import com.google.android.exoplayer2.upstream.HttpUtil;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import java.io.IOException; import java.io.IOException;
@ -289,17 +288,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
responseBody = Assertions.checkNotNull(response.body()); responseBody = Assertions.checkNotNull(response.body());
responseByteStream = responseBody.byteStream(); responseByteStream = responseBody.byteStream();
} catch (IOException e) { } catch (IOException e) {
@Nullable String message = e.getMessage(); throw HttpDataSourceException.createForIOException(
if (message != null e, dataSpec, HttpDataSourceException.TYPE_OPEN);
&& Ascii.toLowerCase(message).matches("cleartext communication.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec);
}
throw new HttpDataSourceException(
"Unable to connect",
e,
dataSpec,
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
HttpDataSourceException.TYPE_OPEN);
} }
int responseCode = response.code(); int responseCode = response.code();
@ -372,11 +362,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
try { try {
return readInternal(buffer, offset, length); return readInternal(buffer, offset, length);
} catch (IOException e) { } catch (IOException e) {
throw new HttpDataSourceException( throw HttpDataSourceException.createForIOException(
e, e, castNonNull(dataSpec), HttpDataSourceException.TYPE_READ);
Assertions.checkNotNull(dataSpec),
PlaybackException.ERROR_CODE_IO_UNSPECIFIED,
HttpDataSourceException.TYPE_READ);
} }
} }

View File

@ -28,7 +28,6 @@ import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.upstream.DataSpec.HttpMethod; import com.google.android.exoplayer2.upstream.DataSpec.HttpMethod;
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.Ascii;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.net.HttpHeaders; import com.google.common.net.HttpHeaders;
import java.io.IOException; import java.io.IOException;
@ -347,35 +346,17 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
bytesToRead = 0; bytesToRead = 0;
transferInitializing(dataSpec); transferInitializing(dataSpec);
try {
connection = makeConnection(dataSpec);
} catch (IOException e) {
@Nullable String message = e.getMessage();
if (message != null
&& Ascii.toLowerCase(message).matches("cleartext http traffic.*not permitted.*")) {
throw new CleartextNotPermittedException(e, dataSpec);
}
throw new HttpDataSourceException(
"Unable to connect",
e,
dataSpec,
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
HttpDataSourceException.TYPE_OPEN);
}
HttpURLConnection connection = this.connection;
String responseMessage; String responseMessage;
HttpURLConnection connection;
try { try {
this.connection = makeConnection(dataSpec);
connection = this.connection;
responseCode = connection.getResponseCode(); responseCode = connection.getResponseCode();
responseMessage = connection.getResponseMessage(); responseMessage = connection.getResponseMessage();
} catch (IOException e) { } catch (IOException e) {
closeConnectionQuietly(); closeConnectionQuietly();
throw new HttpDataSourceException( throw HttpDataSourceException.createForIOException(
"Unable to connect", e, dataSpec, HttpDataSourceException.TYPE_OPEN);
e,
dataSpec,
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
HttpDataSourceException.TYPE_OPEN);
} }
// Check for a valid response code. // Check for a valid response code.
@ -481,11 +462,8 @@ public class DefaultHttpDataSource extends BaseDataSource implements HttpDataSou
try { try {
return readInternal(buffer, offset, length); return readInternal(buffer, offset, length);
} catch (IOException e) { } catch (IOException e) {
throw new HttpDataSourceException( throw HttpDataSourceException.createForIOException(
e, e, castNonNull(dataSpec), HttpDataSourceException.TYPE_READ);
castNonNull(dataSpec),
PlaybackException.ERROR_CODE_IO_UNSPECIFIED,
HttpDataSourceException.TYPE_READ);
} }
} }

View File

@ -26,6 +26,8 @@ import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -207,6 +209,36 @@ public interface HttpDataSource extends DataSource {
/** The error occurred in closing a {@code HttpDataSource}. */ /** The error occurred in closing a {@code HttpDataSource}. */
public static final int TYPE_CLOSE = 3; public static final int TYPE_CLOSE = 3;
/**
* Returns a {@code HttpDataSourceException} whose error code is assigned according to the cause
* and type.
*/
public static HttpDataSourceException createForIOException(
IOException cause, DataSpec dataSpec, @Type int type) {
@PlaybackException.ErrorCode int errorCode = PlaybackException.ERROR_CODE_IO_UNSPECIFIED;
if (cause instanceof SocketTimeoutException) {
errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT;
} else if (cause instanceof UnknownHostException) {
errorCode = PlaybackException.ERROR_CODE_IO_DNS_FAILED;
} else {
@Nullable String message = cause.getMessage();
if (message != null) {
if (Ascii.toLowerCase(message).matches("cleartext.*not permitted.*")) {
errorCode = PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED;
} else if (message.contains("unexpected end of stream")) {
errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED;
}
}
if (type == TYPE_OPEN && errorCode == PlaybackException.ERROR_CODE_IO_UNSPECIFIED) {
errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED;
}
}
return errorCode == PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED
? new CleartextNotPermittedException(cause, dataSpec)
: new HttpDataSourceException(cause, dataSpec, errorCode, type);
}
/** The {@link DataSpec} associated with the current connection. */ /** The {@link DataSpec} associated with the current connection. */
public final DataSpec dataSpec; public final DataSpec dataSpec;