Commit 17723c08 by aquilescanta Committed by Christos Tsilopoulos

Simplify network-related error codes

This change removes ERROR_CODE_IO_NETWORK_UNAVAILABLE,
ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED, and ERROR_CODE_IO_DNS_FAILED
in favor of keeping only ERROR_CODE_IO_NETWORK_CONNECTION_FAILED.

PiperOrigin-RevId: 388715972
parent f23ab8e2
......@@ -669,12 +669,11 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
if (message != null && Ascii.toLowerCase(message).contains("err_cleartext_not_permitted")) {
throw new CleartextNotPermittedException(connectionOpenException, dataSpec);
}
@PlaybackException.ErrorCode
int errorCode =
getErrorCodeForException(
connectionOpenException, /* occurredWhileOpeningConnection*/ true);
throw new OpenException(
connectionOpenException, dataSpec, errorCode, getStatus(urlRequest));
connectionOpenException,
dataSpec,
PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
getStatus(urlRequest));
} else if (!connectionOpened) {
// The timeout was reached before the connection was opened.
throw new OpenException(
......@@ -685,10 +684,13 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// An interruption means the operation is being cancelled, in which case this exception should
// not cause the player to fail. If it does, it likely means that the owner of the operation
// is failing to swallow the interruption, which makes us enter an invalid state.
throw new OpenException(
new InterruptedIOException(),
dataSpec,
PlaybackException.ERROR_CODE_IO_UNSPECIFIED,
PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK,
Status.INVALID);
}
......@@ -1029,7 +1031,9 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
throw new OpenException(
e,
dataSpec,
getErrorCodeForException(e, /* occurredWhileOpeningConnection= */ false),
e instanceof SocketTimeoutException
? PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT
: PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
Status.READING_RESPONSE);
}
}
......@@ -1099,11 +1103,8 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
if (exception instanceof HttpDataSourceException) {
throw (HttpDataSourceException) exception;
} else {
throw new HttpDataSourceException(
exception,
dataSpec,
getErrorCodeForException(exception, /* occurredWhileOpeningConnection= */ false),
HttpDataSourceException.TYPE_READ);
throw HttpDataSourceException.createForIOException(
exception, dataSpec, HttpDataSourceException.TYPE_READ);
}
}
}
......@@ -1116,27 +1117,6 @@ public class CronetDataSource extends BaseDataSource implements HttpDataSource {
return readBuffer;
}
@PlaybackException.ErrorCode
private static int getErrorCodeForException(
IOException exception, boolean occurredWhileOpeningConnection) {
if (exception instanceof UnknownHostException) {
return PlaybackException.ERROR_CODE_IO_DNS_FAILED;
}
@Nullable String message = exception.getMessage();
if (message != null) {
if (message.contains("net::ERR_INTERNET_DISCONNECTED")) {
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) {
return PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED;
}
return PlaybackException.ERROR_CODE_IO_UNSPECIFIED;
}
private static boolean isCompressed(UrlResponseInfo info) {
for (Map.Entry<String, String> entry : info.getAllHeadersAsList()) {
if (entry.getKey().equalsIgnoreCase("Content-Encoding")) {
......
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
......@@ -48,13 +49,10 @@ public class PlaybackException extends Exception implements Bundleable {
ERROR_CODE_TIMEOUT,
ERROR_CODE_FAILED_RUNTIME_CHECK,
ERROR_CODE_IO_UNSPECIFIED,
ERROR_CODE_IO_NETWORK_UNAVAILABLE,
ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED,
ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
ERROR_CODE_IO_BAD_HTTP_STATUS,
ERROR_CODE_IO_DNS_FAILED,
ERROR_CODE_IO_FILE_NOT_FOUND,
ERROR_CODE_IO_NO_PERMISSION,
ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
......@@ -107,32 +105,38 @@ public class PlaybackException extends Exception implements Bundleable {
/** Caused by an Input/Output error which could not be identified. */
public static final int ERROR_CODE_IO_UNSPECIFIED = 2000;
/** Caused by the lack of network connectivity while trying to access a network resource. */
public static final int ERROR_CODE_IO_NETWORK_UNAVAILABLE = 2001;
/** Caused by a failure while establishing a network connection. */
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED = 2002;
/**
* Caused by a network connection failure.
*
* <p>The following is a non-exhaustive list of possible reasons:
*
* <ul>
* <li>There is no network connectivity (you can check this by querying {@link
* ConnectivityManager#getActiveNetwork}).
* <li>The URL's domain is misspelled or does not exist.
* <li>The target host is unreachable.
* <li>The server unexpectedly closes the connection.
* </ul>
*/
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED = 2001;
/** Caused by a network timeout, meaning the server is taking too long to fulfill a request. */
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT = 2003;
/** Caused by an existing connection being unexpectedly closed. */
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED = 2004;
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT = 2002;
/**
* Caused by a server returning a resource with an invalid "Content-Type" HTTP header value.
*
* <p>For example, this can happen when the player is expecting a piece of media, but the server
* returns a paywall HTML page, with content type "text/html".
*/
public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE = 2005;
public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE = 2003;
/** Caused by an HTTP server returning an unexpected HTTP response status code. */
public static final int ERROR_CODE_IO_BAD_HTTP_STATUS = 2006;
/** Caused by the player failing to resolve a hostname. */
public static final int ERROR_CODE_IO_DNS_FAILED = 2007;
public static final int ERROR_CODE_IO_BAD_HTTP_STATUS = 2004;
/** Caused by a non-existent file. */
public static final int ERROR_CODE_IO_FILE_NOT_FOUND = 2008;
public static final int ERROR_CODE_IO_FILE_NOT_FOUND = 2005;
/**
* Caused by lack of permission to perform an IO operation. For example, lack of permission to
* access internet or external storage.
*/
public static final int ERROR_CODE_IO_NO_PERMISSION = 2009;
public static final int ERROR_CODE_IO_NO_PERMISSION = 2006;
/**
* Caused by the player trying to access cleartext HTTP traffic (meaning http:// rather than
* https://) when the app's Network Security Configuration does not permit it.
......@@ -140,9 +144,9 @@ public class PlaybackException extends Exception implements Bundleable {
* <p>See <a href="https://exoplayer.dev/issues/cleartext-not-permitted">this corresponding
* troubleshooting topic</a>.
*/
public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED = 2010;
public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED = 2007;
/** Caused by reading data out of the data bound. */
public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE = 2011;
public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE = 2008;
// Content parsing errors (3xxx).
......@@ -234,20 +238,14 @@ public class PlaybackException extends Exception implements Bundleable {
return "ERROR_CODE_FAILED_RUNTIME_CHECK";
case ERROR_CODE_IO_UNSPECIFIED:
return "ERROR_CODE_IO_UNSPECIFIED";
case ERROR_CODE_IO_NETWORK_UNAVAILABLE:
return "ERROR_CODE_IO_NETWORK_UNAVAILABLE";
case ERROR_CODE_IO_NETWORK_CONNECTION_FAILED:
return "ERROR_CODE_IO_NETWORK_CONNECTION_FAILED";
case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT:
return "ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT";
case ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED:
return "ERROR_CODE_IO_NETWORK_CONNECTION_CLOSED";
case ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE:
return "ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE";
case ERROR_CODE_IO_BAD_HTTP_STATUS:
return "ERROR_CODE_IO_BAD_HTTP_STATUS";
case ERROR_CODE_IO_DNS_FAILED:
return "ERROR_CODE_IO_DNS_FAILED";
case ERROR_CODE_IO_FILE_NOT_FOUND:
return "ERROR_CODE_IO_FILE_NOT_FOUND";
case ERROR_CODE_IO_NO_PERMISSION:
......
......@@ -23,11 +23,11 @@ import com.google.android.exoplayer2.util.Util;
import com.google.common.base.Ascii;
import com.google.common.base.Predicate;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
......@@ -215,24 +215,20 @@ public interface HttpDataSource extends DataSource {
*/
public static HttpDataSourceException createForIOException(
IOException cause, DataSpec dataSpec, @Type int type) {
@PlaybackException.ErrorCode int errorCode = PlaybackException.ERROR_CODE_IO_UNSPECIFIED;
@PlaybackException.ErrorCode int errorCode;
@Nullable String message = cause.getMessage();
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 if (cause instanceof InterruptedIOException) {
// An interruption means the operation is being cancelled, in which case this exception
// should not cause the player to fail. If it does, it likely means that the owner of the
// operation is failing to swallow the interruption, which makes us enter an invalid state.
errorCode = PlaybackException.ERROR_CODE_FAILED_RUNTIME_CHECK;
} else if (message != null
&& Ascii.toLowerCase(message).matches("cleartext.*not permitted.*")) {
errorCode = PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED;
} 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;
}
errorCode = PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED;
}
return errorCode == PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED
? new CleartextNotPermittedException(cause, dataSpec)
......
......@@ -22,16 +22,12 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.PlaybackException;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.PortUnreachableException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
/** A UDP {@link DataSource}. */
public final class UdpDataSource extends BaseDataSource {
......@@ -115,25 +111,14 @@ public final class UdpDataSource extends BaseDataSource {
} else {
socket = new DatagramSocket(socketAddress);
}
socket.setSoTimeout(socketTimeoutMillis);
} catch (SecurityException e) {
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_NO_PERMISSION);
} catch (UnknownHostException e) {
// TODO (internal b/184262323): Handle the case where UnknownHostException is thrown due to
// lack of network access.
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_DNS_FAILED);
} catch (BindException e) {
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_NETWORK_UNAVAILABLE);
} catch (IOException e) {
throw new UdpDataSourceException(
e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED);
}
try {
socket.setSoTimeout(socketTimeoutMillis);
} catch (SocketException e) {
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED);
}
opened = true;
transferStarted(dataSpec);
return C.LENGTH_UNSET;
......@@ -149,13 +134,12 @@ public final class UdpDataSource extends BaseDataSource {
// We've read all of the data from the current packet. Get another.
try {
socket.receive(packet);
} catch (PortUnreachableException e) {
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_NETWORK_UNAVAILABLE);
} catch (SocketTimeoutException e) {
throw new UdpDataSourceException(
e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT);
} catch (IOException e) {
throw new UdpDataSourceException(e, PlaybackException.ERROR_CODE_IO_UNSPECIFIED);
throw new UdpDataSourceException(
e, PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED);
}
packetRemaining = packet.getLength();
bytesTransferred(packetRemaining);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment