Make PlaybackException's Bundleable implementation subclass friendly

PiperOrigin-RevId: 372552003
This commit is contained in:
aquilescanta 2021-05-07 15:31:44 +01:00 committed by Andrew Lewis
parent 1a6984fbe0
commit f415ea2372

View File

@ -192,7 +192,20 @@ public class PlaybackException extends Exception implements Bundleable {
this(message, cause, errorCode, Clock.DEFAULT.elapsedRealtime()); this(message, cause, errorCode, Clock.DEFAULT.elapsedRealtime());
} }
private PlaybackException( /** Creates a new instance using the fields obtained from the given {@link Bundle}. */
protected PlaybackException(Bundle bundle) {
this(
/* message= */ bundle.getString(keyForField(FIELD_STRING_MESSAGE)),
/* cause= */ getCauseFromBundle(bundle),
/* errorCode= */ bundle.getInt(
keyForField(FIELD_INT_ERROR_CODE), /* defaultValue= */ ERROR_CODE_UNSPECIFIED),
/* timestampMs= */ bundle.getLong(
keyForField(FIELD_LONG_TIMESTAMP_MS),
/* defaultValue= */ SystemClock.elapsedRealtime()));
}
/** Creates a new instance using the given values. */
protected PlaybackException(
@Nullable String message, @Nullable String message,
@Nullable Throwable cause, @Nullable Throwable cause,
@ErrorCode int errorCode, @ErrorCode int errorCode,
@ -227,9 +240,6 @@ public class PlaybackException extends Exception implements Bundleable {
private static final int FIELD_STRING_CAUSE_CLASS_NAME = 3; private static final int FIELD_STRING_CAUSE_CLASS_NAME = 3;
private static final int FIELD_STRING_CAUSE_MESSAGE = 4; private static final int FIELD_STRING_CAUSE_MESSAGE = 4;
/** Object that can restore {@link PlaybackException} from a {@link Bundle}. */
public static final Creator<PlaybackException> CREATOR = PlaybackException::fromBundle;
/** /**
* Defines a minimum field id value for subclasses to use when implementing {@link #toBundle()} * Defines a minimum field id value for subclasses to use when implementing {@link #toBundle()}
* and {@link Bundleable.Creator}. * and {@link Bundleable.Creator}.
@ -239,6 +249,9 @@ public class PlaybackException extends Exception implements Bundleable {
*/ */
protected static final int FIELD_CUSTOM_ID_BASE = 1000; protected static final int FIELD_CUSTOM_ID_BASE = 1000;
/** Object that can create a {@link PlaybackException} from a {@link Bundle}. */
public static final Creator<PlaybackException> CREATOR = PlaybackException::new;
@CallSuper @CallSuper
@Override @Override
public Bundle toBundle() { public Bundle toBundle() {
@ -254,47 +267,6 @@ public class PlaybackException extends Exception implements Bundleable {
return bundle; return bundle;
} }
/**
* Creates and returns a new instance using the field data in the given {@link Bundle}.
*
* @param bundle The {@link Bundle} from which to obtain the returned instance's contents.
* @return The created instance.
*/
protected static PlaybackException fromBundle(Bundle bundle) {
@ErrorCode
int errorCode =
bundle.getInt(
keyForField(FIELD_INT_ERROR_CODE), /* defaultValue= */ ERROR_CODE_UNSPECIFIED);
long timestampMs =
bundle.getLong(
keyForField(FIELD_LONG_TIMESTAMP_MS),
/* defaultValue= */ SystemClock.elapsedRealtime());
@Nullable String message = bundle.getString(keyForField(FIELD_STRING_MESSAGE));
@Nullable String causeClassName = bundle.getString(keyForField(FIELD_STRING_CAUSE_CLASS_NAME));
@Nullable String causeMessage = bundle.getString(keyForField(FIELD_STRING_CAUSE_MESSAGE));
@Nullable Throwable cause = null;
if (!TextUtils.isEmpty(causeClassName)) {
try {
Class<?> clazz =
Class.forName(
causeClassName, /* initialize= */ true, PlaybackException.class.getClassLoader());
if (Throwable.class.isAssignableFrom(clazz)) {
cause = createThrowable(clazz, causeMessage);
}
} catch (Throwable e) {
// There was an error while creating the cause using reflection, do nothing here and let the
// finally block handle the issue.
} finally {
if (cause == null) {
// The bundle has fields to represent the cause, but we were unable to re-create the
// exception using reflection. We instantiate a RemoteException to reflect this problem.
cause = createRemoteException(causeMessage);
}
}
}
return new PlaybackException(message, cause, errorCode, timestampMs);
}
/** /**
* Converts the given {@link FieldNumber} to a string which can be used as a field key when * Converts the given {@link FieldNumber} to a string which can be used as a field key when
* implementing {@link #toBundle()} and {@link Bundleable.Creator}. * implementing {@link #toBundle()} and {@link Bundleable.Creator}.
@ -315,4 +287,31 @@ public class PlaybackException extends Exception implements Bundleable {
private static RemoteException createRemoteException(@Nullable String message) { private static RemoteException createRemoteException(@Nullable String message) {
return new RemoteException(message); return new RemoteException(message);
} }
@Nullable
private static Throwable getCauseFromBundle(Bundle bundle) {
@Nullable String causeClassName = bundle.getString(keyForField(FIELD_STRING_CAUSE_CLASS_NAME));
@Nullable String causeMessage = bundle.getString(keyForField(FIELD_STRING_CAUSE_MESSAGE));
@Nullable Throwable cause = null;
if (!TextUtils.isEmpty(causeClassName)) {
try {
Class<?> clazz =
Class.forName(
causeClassName, /* initialize= */ true, PlaybackException.class.getClassLoader());
if (Throwable.class.isAssignableFrom(clazz)) {
cause = createThrowable(clazz, causeMessage);
}
} catch (Throwable e) {
// There was an error while creating the cause using reflection, do nothing here and let the
// finally block handle the issue.
} finally {
if (cause == null) {
// The bundle has fields to represent the cause, but we were unable to re-create the
// exception using reflection. We instantiate a RemoteException to reflect this problem.
cause = createRemoteException(causeMessage);
}
}
}
return cause;
}
} }