Commit 2b67f2a6 by andrewlewis Committed by Andrew Lewis

Avoid crashing process on OOM

Catch OutOfMemoryErrors and surface them as unexpected ExoPlaybackExceptions.

PiperOrigin-RevId: 234481140
parent 0ceff589
......@@ -31,11 +31,11 @@ public final class ExoPlaybackException extends Exception {
/**
* The type of source that produced the error. One of {@link #TYPE_SOURCE}, {@link #TYPE_RENDERER}
* or {@link #TYPE_UNEXPECTED}.
* {@link #TYPE_UNEXPECTED}, {@link #TYPE_REMOTE} or {@link #TYPE_OUT_OF_MEMORY}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_SOURCE, TYPE_RENDERER, TYPE_UNEXPECTED, TYPE_REMOTE})
@IntDef({TYPE_SOURCE, TYPE_RENDERER, TYPE_UNEXPECTED, TYPE_REMOTE, TYPE_OUT_OF_MEMORY})
public @interface Type {}
/**
* The error occurred loading data from a {@link MediaSource}.
......@@ -61,10 +61,12 @@ public final class ExoPlaybackException extends Exception {
* <p>Call {@link #getMessage()} to retrieve the message associated with the error.
*/
public static final int TYPE_REMOTE = 3;
/** The error was an {@link OutOfMemoryError}. */
public static final int TYPE_OUT_OF_MEMORY = 4;
/**
* The type of the playback failure. One of {@link #TYPE_SOURCE}, {@link #TYPE_RENDERER} and
* {@link #TYPE_UNEXPECTED}.
* The type of the playback failure. One of {@link #TYPE_SOURCE}, {@link #TYPE_RENDERER}, {@link
* #TYPE_UNEXPECTED}, {@link #TYPE_REMOTE} and {@link #TYPE_OUT_OF_MEMORY}.
*/
@Type public final int type;
......@@ -82,7 +84,7 @@ public final class ExoPlaybackException extends Exception {
* @return The created instance.
*/
public static ExoPlaybackException createForSource(IOException cause) {
return new ExoPlaybackException(TYPE_SOURCE, cause, C.INDEX_UNSET);
return new ExoPlaybackException(TYPE_SOURCE, cause, /* rendererIndex= */ C.INDEX_UNSET);
}
/**
......@@ -103,7 +105,7 @@ public final class ExoPlaybackException extends Exception {
* @return The created instance.
*/
/* package */ static ExoPlaybackException createForUnexpected(RuntimeException cause) {
return new ExoPlaybackException(TYPE_UNEXPECTED, cause, C.INDEX_UNSET);
return new ExoPlaybackException(TYPE_UNEXPECTED, cause, /* rendererIndex= */ C.INDEX_UNSET);
}
/**
......@@ -116,6 +118,16 @@ public final class ExoPlaybackException extends Exception {
return new ExoPlaybackException(TYPE_REMOTE, message);
}
/**
* Creates an instance of type {@link #TYPE_OUT_OF_MEMORY}.
*
* @param cause The cause of the failure.
* @return The created instance.
*/
/* package */ static ExoPlaybackException createForOutOfMemoryError(OutOfMemoryError cause) {
return new ExoPlaybackException(TYPE_OUT_OF_MEMORY, cause, /* rendererIndex= */ C.INDEX_UNSET);
}
private ExoPlaybackException(@Type int type, Throwable cause, int rendererIndex) {
super(cause);
this.type = type;
......@@ -160,4 +172,13 @@ public final class ExoPlaybackException extends Exception {
return (RuntimeException) Assertions.checkNotNull(cause);
}
/**
* Retrieves the underlying error when {@link #type} is {@link #TYPE_OUT_OF_MEMORY}.
*
* @throws IllegalStateException If {@link #type} is not {@link #TYPE_OUT_OF_MEMORY}.
*/
public OutOfMemoryError getOutOfMemoryError() {
Assertions.checkState(type == TYPE_OUT_OF_MEMORY);
return (OutOfMemoryError) Assertions.checkNotNull(cause);
}
}
......@@ -389,14 +389,17 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* acknowledgeStop= */ false);
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForSource(e)).sendToTarget();
maybeNotifyPlaybackInfoChanged();
} catch (RuntimeException e) {
} catch (RuntimeException | OutOfMemoryError e) {
Log.e(TAG, "Internal runtime error.", e);
stopInternal(
/* forceResetRenderers= */ true,
/* resetPositionAndState= */ false,
/* acknowledgeStop= */ false);
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForUnexpected(e))
.sendToTarget();
ExoPlaybackException error =
e instanceof OutOfMemoryError
? ExoPlaybackException.createForOutOfMemoryError((OutOfMemoryError) e)
: ExoPlaybackException.createForUnexpected((RuntimeException) e);
eventHandler.obtainMessage(MSG_ERROR, error).sendToTarget();
maybeNotifyPlaybackInfoChanged();
}
return true;
......
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