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, MediaMetadataCompat.METADATA_KEY_DOWNLOAD_STATUS,
MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT); 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}. */ /** Converts {@link PlaybackStateCompat} to {@link PlaybackException}. */
@Nullable @Nullable
public static PlaybackException convertToPlaybackException( public static PlaybackException convertToPlaybackException(
@ -810,11 +821,16 @@ import java.util.concurrent.TimeoutException;
return false; 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( public static @Player.State int convertToPlaybackState(
@Nullable PlaybackStateCompat playbackStateCompat, @Nullable PlaybackStateCompat playbackStateCompat,
@Nullable MediaMetadataCompat currentMediaMetadata, @Nullable MediaMetadataCompat currentMediaMetadata,
long timeDiffMs) { long timeDiffMs)
throws ConversionException {
if (playbackStateCompat == null) { if (playbackStateCompat == null) {
return Player.STATE_IDLE; return Player.STATE_IDLE;
} }
@ -842,8 +858,8 @@ import java.util.concurrent.TimeoutException;
convertToCurrentPositionMs(playbackStateCompat, currentMediaMetadata, timeDiffMs); convertToCurrentPositionMs(playbackStateCompat, currentMediaMetadata, timeDiffMs);
return (currentPosition < duration) ? Player.STATE_READY : Player.STATE_ENDED; return (currentPosition < duration) ? Player.STATE_READY : Player.STATE_ENDED;
default: default:
throw new IllegalStateException( throw new ConversionException(
"Unrecognized PlaybackStateCompat: " + playbackStateCompat.getState()); "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 androidx.media3.session.MediaUtils.calculateBufferedPercentage;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
import static java.lang.String.format;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; 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.NullableType;
import androidx.media3.common.util.Size; import androidx.media3.common.util.Size;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.session.LegacyConversions.ConversionException;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -1491,6 +1493,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
legacyPlayerInfo, legacyPlayerInfo,
controllerInfo, controllerInfo,
newLegacyPlayerInfo, newLegacyPlayerInfo,
controllerCompat.getPackageName(),
controllerCompat.getFlags(), controllerCompat.getFlags(),
controllerCompat.isSessionReady(), controllerCompat.isSessionReady(),
controllerCompat.getRatingType(), controllerCompat.getRatingType(),
@ -1877,6 +1880,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
LegacyPlayerInfo oldLegacyPlayerInfo, LegacyPlayerInfo oldLegacyPlayerInfo,
ControllerInfo oldControllerInfo, ControllerInfo oldControllerInfo,
LegacyPlayerInfo newLegacyPlayerInfo, LegacyPlayerInfo newLegacyPlayerInfo,
String sessionPackageName,
long sessionFlags, long sessionFlags,
boolean isSessionReady, boolean isSessionReady,
@RatingCompat.Style int ratingType, @RatingCompat.Style int ratingType,
@ -2027,12 +2031,21 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
LegacyConversions.convertToAudioAttributes(newLegacyPlayerInfo.playbackInfoCompat); LegacyConversions.convertToAudioAttributes(newLegacyPlayerInfo.playbackInfoCompat);
boolean playWhenReady = boolean playWhenReady =
LegacyConversions.convertToPlayWhenReady(newLegacyPlayerInfo.playbackStateCompat); LegacyConversions.convertToPlayWhenReady(newLegacyPlayerInfo.playbackStateCompat);
@Player.State @Player.State int playbackState;
int playbackState = try {
playbackState =
LegacyConversions.convertToPlaybackState( LegacyConversions.convertToPlaybackState(
newLegacyPlayerInfo.playbackStateCompat, newLegacyPlayerInfo.playbackStateCompat,
newLegacyPlayerInfo.mediaMetadataCompat, newLegacyPlayerInfo.mediaMetadataCompat,
timeDiffMs); 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 = boolean isPlaying =
LegacyConversions.convertToIsPlaying(newLegacyPlayerInfo.playbackStateCompat); LegacyConversions.convertToIsPlaying(newLegacyPlayerInfo.playbackStateCompat);
DeviceInfo deviceInfo = DeviceInfo deviceInfo =