Don't crash when receiving a bad playback state

PiperOrigin-RevId: 580942377
(cherry picked from commit e79809616cd0ecb6f39cbeffdaaf143c260f64e6)
This commit is contained in:
Googler 2023-11-09 09:58:17 -08:00 committed by microkatz
parent f189af5632
commit 2db9da5c1d
2 changed files with 39 additions and 10 deletions

View File

@ -143,6 +143,17 @@ import java.util.concurrent.TimeoutException;
MediaMetadataCompat.METADATA_KEY_DOWNLOAD_STATUS,
MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT);
/** Exception thrown when the conversion between legacy and Media3 states fails. */
public static class ConversionException extends Exception {
private ConversionException(String message) {
super(message);
}
private ConversionException(String message, Throwable cause) {
super(message, cause);
}
}
/** Converts {@link PlaybackStateCompat} to {@link PlaybackException}. */
@Nullable
public static PlaybackException convertToPlaybackException(
@ -810,11 +821,16 @@ import java.util.concurrent.TimeoutException;
return false;
}
/** Converts a {@link PlaybackStateCompat} to {@link Player.State} */
/**
* Converts a {@link PlaybackStateCompat} to {@link Player.State}
*
* @throws ConversionException if the legacy state of the remote session is invalid
*/
public static @Player.State int convertToPlaybackState(
@Nullable PlaybackStateCompat playbackStateCompat,
@Nullable MediaMetadataCompat currentMediaMetadata,
long timeDiffMs) {
long timeDiffMs)
throws ConversionException {
if (playbackStateCompat == null) {
return Player.STATE_IDLE;
}
@ -842,8 +858,8 @@ import java.util.concurrent.TimeoutException;
convertToCurrentPositionMs(playbackStateCompat, currentMediaMetadata, timeDiffMs);
return (currentPosition < duration) ? Player.STATE_READY : Player.STATE_ENDED;
default:
throw new IllegalStateException(
"Unrecognized PlaybackStateCompat: " + playbackStateCompat.getState());
throw new ConversionException(
"Invalid state of PlaybackStateCompat: " + playbackStateCompat.getState());
}
}

View File

@ -22,6 +22,7 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.session.MediaUtils.calculateBufferedPercentage;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.String.format;
import android.app.PendingIntent;
import android.content.Context;
@ -73,6 +74,7 @@ import androidx.media3.common.util.Log;
import androidx.media3.common.util.NullableType;
import androidx.media3.common.util.Size;
import androidx.media3.common.util.Util;
import androidx.media3.session.LegacyConversions.ConversionException;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -1491,6 +1493,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
legacyPlayerInfo,
controllerInfo,
newLegacyPlayerInfo,
controllerCompat.getPackageName(),
controllerCompat.getFlags(),
controllerCompat.isSessionReady(),
controllerCompat.getRatingType(),
@ -1877,6 +1880,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
LegacyPlayerInfo oldLegacyPlayerInfo,
ControllerInfo oldControllerInfo,
LegacyPlayerInfo newLegacyPlayerInfo,
String sessionPackageName,
long sessionFlags,
boolean isSessionReady,
@RatingCompat.Style int ratingType,
@ -2027,12 +2031,21 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
LegacyConversions.convertToAudioAttributes(newLegacyPlayerInfo.playbackInfoCompat);
boolean playWhenReady =
LegacyConversions.convertToPlayWhenReady(newLegacyPlayerInfo.playbackStateCompat);
@Player.State
int playbackState =
@Player.State int playbackState;
try {
playbackState =
LegacyConversions.convertToPlaybackState(
newLegacyPlayerInfo.playbackStateCompat,
newLegacyPlayerInfo.mediaMetadataCompat,
timeDiffMs);
} catch (ConversionException e) {
Log.e(
TAG,
format(
"Received invalid playback state %s from package %s. Keeping the previous state.",
newLegacyPlayerInfo.playbackStateCompat.getState(), sessionPackageName));
playbackState = oldControllerInfo.playerInfo.playbackState;
}
boolean isPlaying =
LegacyConversions.convertToIsPlaying(newLegacyPlayerInfo.playbackStateCompat);
DeviceInfo deviceInfo =