Align PlaybackStateCompat states with logic in MediaSessionConnector

Creating the PlaybackStateCompat from a media3 Player state is done
already by the MediaSessionConnector (and used widely). The media3
session module should set the same states under the same circumstances
to ensure compatiblity and consistency.

PlaybackStateCompat changes made in media3 session:
 - Use STATE_STOPPED when player is ended instead of STATE_PAUSED
 - Use STATE_PLAYING when playback is suppressed temporarily.
 - Set the playback speed to 0 if the player is not playing.
 - Add extras for mediaId and user-set playback speed.

Part of the problem was that Player.isPlaying() was used to check
the state. Unfortunately, MockPlayer.isPlaying() is implemented in
a way that makes it hard to test these changes, because the value
is set independently of playbackState, playWhenReady and suppression
reason. To be able to write consistent, logical tests, this change
also removes the independent setting of isPlaying in MockPlayer to
align it better with a real player. This requires to update some
other tests to use alternative methods.

PiperOrigin-RevId: 487500859
This commit is contained in:
tonihei 2022-11-10 12:40:37 +00:00 committed by microkatz
parent 4f04a284ed
commit c5e071e556
13 changed files with 280 additions and 102 deletions

View File

@ -32,7 +32,7 @@ import androidx.media3.session.MediaLibraryService.MediaLibrarySession;
public final class MediaConstants { public final class MediaConstants {
/** /**
* The legacy error code for expired authentication. * {@link Bundle} key used for the error code for expired authentication.
* *
* <p>Use this error code to indicate an expired authentication when {@linkplain * <p>Use this error code to indicate an expired authentication when {@linkplain
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful * LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
@ -43,7 +43,23 @@ public final class MediaConstants {
public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3; public static final int ERROR_CODE_AUTHENTICATION_EXPIRED_COMPAT = 3;
/** /**
* The extras key for the localized error resolution string. * {@link Bundle} key used for the value of {@code Player.getPlaybackParameters().speed}.
*
* <p>Use this key in the extras bundle of the legacy {@link PlaybackStateCompat}.
*/
@UnstableApi public static final String EXTRAS_KEY_PLAYBACK_SPEED_COMPAT = "EXO_SPEED";
/**
* {@link Bundle} key used for the media id of the media being played.
*
* <p>Use this key in the extras bundle of the legacy {@link PlaybackStateCompat}.
*/
@UnstableApi
public static final String EXTRAS_KEY_MEDIA_ID_COMPAT =
androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID;
/**
* {@link Bundle} key used for a localized error resolution string.
* *
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain * <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful * LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful
@ -53,7 +69,7 @@ public final class MediaConstants {
androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL; androidx.media.utils.MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL;
/** /**
* The extras key for the error resolution intent. * {@link Bundle} key used for an error resolution intent.
* *
* <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain * <p>Use this key to populate the extras bundle of the {@link LibraryParams} when {@linkplain
* LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful * LibraryResult#ofError(int, LibraryParams) creating a library result} for an unsuccessful

View File

@ -728,20 +728,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public static int convertToPlaybackStateCompatState( public static int convertToPlaybackStateCompatState(
@Nullable PlaybackException playerError, @Nullable PlaybackException playerError,
@Player.State int playbackState, @Player.State int playbackState,
boolean playWhenReady, boolean playWhenReady) {
boolean isPlaying) {
if (playerError != null) { if (playerError != null) {
return PlaybackStateCompat.STATE_ERROR; return PlaybackStateCompat.STATE_ERROR;
} }
if (isPlaying) {
return PlaybackStateCompat.STATE_PLAYING;
}
switch (playbackState) { switch (playbackState) {
case Player.STATE_IDLE: case Player.STATE_IDLE:
return PlaybackStateCompat.STATE_NONE; return PlaybackStateCompat.STATE_NONE;
case Player.STATE_READY: case Player.STATE_READY:
return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED;
case Player.STATE_ENDED: case Player.STATE_ENDED:
return PlaybackStateCompat.STATE_PAUSED; return PlaybackStateCompat.STATE_STOPPED;
case Player.STATE_BUFFERING: case Player.STATE_BUFFERING:
return playWhenReady return playWhenReady
? PlaybackStateCompat.STATE_BUFFERING ? PlaybackStateCompat.STATE_BUFFERING

View File

@ -18,6 +18,8 @@ package androidx.media3.session;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.postOrRun; import static androidx.media3.common.util.Util.postOrRun;
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_MEDIA_ID_COMPAT;
import static androidx.media3.session.MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
@ -768,7 +770,7 @@ import java.util.List;
@Nullable PlaybackException playerError = getPlayerError(); @Nullable PlaybackException playerError = getPlayerError();
int state = int state =
MediaUtils.convertToPlaybackStateCompatState( MediaUtils.convertToPlaybackStateCompatState(
playerError, getPlaybackState(), getPlayWhenReady(), isPlaying()); playerError, getPlaybackState(), getPlayWhenReady());
long allActions = long allActions =
PlaybackStateCompat.ACTION_STOP PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PAUSE
@ -798,16 +800,22 @@ import java.util.List;
allActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT; allActions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
} }
long queueItemId = MediaUtils.convertToQueueItemId(getCurrentMediaItemIndex()); long queueItemId = MediaUtils.convertToQueueItemId(getCurrentMediaItemIndex());
float playbackSpeed = getPlaybackParameters().speed;
float sessionPlaybackSpeed = isPlaying() ? playbackSpeed : 0f;
Bundle extras = new Bundle();
extras.putFloat(EXTRAS_KEY_PLAYBACK_SPEED_COMPAT, playbackSpeed);
@Nullable MediaItem currentMediaItem = getCurrentMediaItem();
if (currentMediaItem != null && !MediaItem.DEFAULT_MEDIA_ID.equals(currentMediaItem.mediaId)) {
extras.putString(EXTRAS_KEY_MEDIA_ID_COMPAT, currentMediaItem.mediaId);
}
PlaybackStateCompat.Builder builder = PlaybackStateCompat.Builder builder =
new PlaybackStateCompat.Builder() new PlaybackStateCompat.Builder()
.setState( .setState(
state, state, getCurrentPosition(), sessionPlaybackSpeed, SystemClock.elapsedRealtime())
getCurrentPosition(),
getPlaybackParameters().speed,
SystemClock.elapsedRealtime())
.setActions(allActions) .setActions(allActions)
.setActiveQueueItemId(queueItemId) .setActiveQueueItemId(queueItemId)
.setBufferedPosition(getBufferedPosition()); .setBufferedPosition(getBufferedPosition())
.setExtras(extras);
for (int i = 0; i < customLayout.size(); i++) { for (int i = 0; i < customLayout.size(); i++) {
CommandButton commandButton = customLayout.get(i); CommandButton commandButton = customLayout.get(i);

View File

@ -55,7 +55,6 @@ interface IRemoteMediaSession {
void notifyPlayerError(String sessionId, in Bundle playerErrorBundle); void notifyPlayerError(String sessionId, in Bundle playerErrorBundle);
void notifyPlayWhenReadyChanged(String sessionId, boolean playWhenReady, int reason); void notifyPlayWhenReadyChanged(String sessionId, boolean playWhenReady, int reason);
void notifyPlaybackStateChanged(String sessionId, int state); void notifyPlaybackStateChanged(String sessionId, int state);
void notifyIsPlayingChanged(String sessionId, boolean isPlaying);
void notifyIsLoadingChanged(String sessionId, boolean isLoading); void notifyIsLoadingChanged(String sessionId, boolean isLoading);
void notifyPositionDiscontinuity(String sessionId, void notifyPositionDiscontinuity(String sessionId,
in Bundle oldPositionBundle, in Bundle newPositionBundle, int reason); in Bundle oldPositionBundle, in Bundle newPositionBundle, int reason);

View File

@ -90,7 +90,6 @@ public class CommonConstants {
public static final String KEY_PLAY_WHEN_READY = "playWhenReady"; public static final String KEY_PLAY_WHEN_READY = "playWhenReady";
public static final String KEY_PLAYBACK_SUPPRESSION_REASON = "playbackSuppressionReason"; public static final String KEY_PLAYBACK_SUPPRESSION_REASON = "playbackSuppressionReason";
public static final String KEY_PLAYBACK_STATE = "playbackState"; public static final String KEY_PLAYBACK_STATE = "playbackState";
public static final String KEY_IS_PLAYING = "isPlaying";
public static final String KEY_IS_LOADING = "isLoading"; public static final String KEY_IS_LOADING = "isLoading";
public static final String KEY_REPEAT_MODE = "repeatMode"; public static final String KEY_REPEAT_MODE = "repeatMode";
public static final String KEY_SHUFFLE_MODE_ENABLED = "shuffleModeEnabled"; public static final String KEY_SHUFFLE_MODE_ENABLED = "shuffleModeEnabled";

View File

@ -338,7 +338,6 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
} }
}); });
assertThat(errorLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(errorLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(lastReportedPlaybackStateCompat).isNotNull();
assertThat(lastReportedPlaybackStateCompat.getState()) assertThat(lastReportedPlaybackStateCompat.getState())
.isEqualTo(PlaybackStateCompat.STATE_ERROR); .isEqualTo(PlaybackStateCompat.STATE_ERROR);
assertThat( assertThat(
@ -361,7 +360,11 @@ public class MediaBrowserCompatWithMediaLibraryServiceTest
// Any successful calls remove the error state, // Any successful calls remove the error state,
assertThat(lastReportedPlaybackStateCompat.getState()) assertThat(lastReportedPlaybackStateCompat.getState())
.isNotEqualTo(PlaybackStateCompat.STATE_ERROR); .isNotEqualTo(PlaybackStateCompat.STATE_ERROR);
assertThat(lastReportedPlaybackStateCompat.getExtras()).isNull(); assertThat(
lastReportedPlaybackStateCompat
.getExtras()
.getString(MediaConstants.EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL_COMPAT))
.isNull();
} }
@Test @Test

View File

@ -123,6 +123,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
Bundle playerConfig = Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder() new RemoteMediaSession.MockPlayerConfigBuilder()
.setPlaybackState(testState) .setPlaybackState(testState)
.setPlayWhenReady(true)
.setBufferedPosition(testBufferingPosition) .setBufferedPosition(testBufferingPosition)
.setPlaybackParameters(new PlaybackParameters(testSpeed)) .setPlaybackParameters(new PlaybackParameters(testSpeed))
.setTimeline(testTimeline) .setTimeline(testTimeline)
@ -153,7 +154,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
.isEqualTo(testState); .isEqualTo(testState);
assertThat(controller.getPlaybackState().getBufferedPosition()) assertThat(controller.getPlaybackState().getBufferedPosition())
.isEqualTo(testBufferingPosition); .isEqualTo(testBufferingPosition);
assertThat(controller.getPlaybackState().getPlaybackSpeed()).isWithin(EPSILON).of(testSpeed); assertThat(controller.getPlaybackState().getPlaybackSpeed()).isEqualTo(testSpeed);
assertThat(controller.getMetadata().getString(METADATA_KEY_MEDIA_ID)) assertThat(controller.getMetadata().getString(METADATA_KEY_MEDIA_ID))
.isEqualTo(testMediaItems.get(testItemIndex).mediaId); .isEqualTo(testMediaItems.get(testItemIndex).mediaId);
@ -380,9 +381,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
assertThat(latchForPlaybackState.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latchForPlaybackState.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateRef.get().getBufferedPosition()).isEqualTo(testBufferedPositionMs); assertThat(playbackStateRef.get().getBufferedPosition()).isEqualTo(testBufferedPositionMs);
assertThat(playbackStateRef.get().getPosition()).isEqualTo(testCurrentPositionMs); assertThat(playbackStateRef.get().getPosition()).isEqualTo(testCurrentPositionMs);
assertThat(playbackStateRef.get().getPlaybackSpeed()) assertThat(playbackStateRef.get().getPlaybackSpeed()).isEqualTo(playbackParameters.speed);
.isWithin(EPSILON)
.of(playbackParameters.speed);
assertThat(latchForMetadata.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latchForMetadata.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(metadataRef.get().getString(METADATA_KEY_MEDIA_ID)) assertThat(metadataRef.get().getString(METADATA_KEY_MEDIA_ID))
@ -604,7 +603,10 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
@Test @Test
public void onPlaybackParametersChanged_notifiesPlaybackStateCompatChanges() throws Exception { public void onPlaybackParametersChanged_notifiesPlaybackStateCompatChanges() throws Exception {
PlaybackParameters playbackParameters = new PlaybackParameters(/* speed= */ 1.5f); PlaybackParameters playbackParameters = new PlaybackParameters(/* speed= */ 1.5f);
session.getMockPlayer().setPlaybackState(Player.STATE_READY);
session
.getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
AtomicReference<PlaybackStateCompat> playbackStateRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
MediaControllerCompat.Callback callback = MediaControllerCompat.Callback callback =
@ -619,12 +621,21 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
session.getMockPlayer().notifyPlaybackParametersChanged(playbackParameters); session.getMockPlayer().notifyPlaybackParametersChanged(playbackParameters);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateRef.get().getPlaybackSpeed()) assertThat(playbackStateRef.get().getPlaybackSpeed()).isEqualTo(playbackParameters.speed);
.isWithin(EPSILON) assertThat(
.of(playbackParameters.speed); playbackStateRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(playbackParameters.speed);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()) assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed())
.isWithin(EPSILON) .isEqualTo(playbackParameters.speed);
.of(playbackParameters.speed); assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(playbackParameters.speed);
} }
@Test @Test
@ -632,11 +643,8 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
throws Exception { throws Exception {
session session
.getMockPlayer() .getMockPlayer()
.setPlayWhenReady( .setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
/* playWhenReady= */ true,
Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS);
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY); session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
session.getMockPlayer().notifyIsPlayingChanged(false);
AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -657,6 +665,28 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateCompatRef.get().getState()).isEqualTo(PlaybackStateCompat.STATE_PAUSED); assertThat(playbackStateCompatRef.get().getState()).isEqualTo(PlaybackStateCompat.STATE_PAUSED);
assertThat(playbackStateCompatRef.get().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(controllerCompat.getPlaybackState().getState())
.isEqualTo(PlaybackStateCompat.STATE_PAUSED);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
} }
@Test @Test
@ -666,7 +696,6 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
.getMockPlayer() .getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ false, Player.PLAYBACK_SUPPRESSION_REASON_NONE); .setPlayWhenReady(/* playWhenReady= */ false, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
session.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_BUFFERING); session.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_BUFFERING);
session.getMockPlayer().notifyIsPlayingChanged(false);
AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -687,17 +716,36 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
assertThat(playbackStateCompatRef.get().getState()) assertThat(playbackStateCompatRef.get().getState())
.isEqualTo(PlaybackStateCompat.STATE_BUFFERING); .isEqualTo(PlaybackStateCompat.STATE_BUFFERING);
assertThat(playbackStateCompatRef.get().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(controllerCompat.getPlaybackState().getState())
.isEqualTo(PlaybackStateCompat.STATE_BUFFERING);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
} }
@Test @Test
public void playbackStateChange_playbackStateBecomesEnded_notifiesPaused() throws Exception { public void playbackStateChange_playbackStateBecomesEnded_notifiesStopped() throws Exception {
session session
.getMockPlayer() .getMockPlayer()
.setPlayWhenReady( .setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
/* playWhenReady= */ true,
Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS);
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY); session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
session.getMockPlayer().notifyIsPlayingChanged(false);
AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -714,12 +762,39 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
session.getMockPlayer().notifyPlaybackStateChanged(STATE_ENDED); session.getMockPlayer().notifyPlaybackStateChanged(STATE_ENDED);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateCompatRef.get().getState()).isEqualTo(PlaybackStateCompat.STATE_PAUSED); assertThat(playbackStateCompatRef.get().getState())
.isEqualTo(PlaybackStateCompat.STATE_STOPPED);
assertThat(playbackStateCompatRef.get().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(controllerCompat.getPlaybackState().getState())
.isEqualTo(PlaybackStateCompat.STATE_STOPPED);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
} }
@Test @Test
public void playbackStateChange_isPlayingBecomesTrue_notifiesPlaying() throws Exception { public void playbackStateChange_withPlaybackSuppression_notifiesPlayingWithSpeedZero()
session.getMockPlayer().notifyIsPlayingChanged(false); throws Exception {
session.getMockPlayer().setPlaybackState(Player.STATE_READY);
session
.getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
@ -733,11 +808,83 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
}; };
controllerCompat.registerCallback(callback, handler); controllerCompat.registerCallback(callback, handler);
session.getMockPlayer().notifyIsPlayingChanged(true); session
.getMockPlayer()
.notifyPlayWhenReadyChanged(
/* playWhenReady= */ true,
Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateCompatRef.get().getState()) assertThat(playbackStateCompatRef.get().getState())
.isEqualTo(PlaybackStateCompat.STATE_PLAYING); .isEqualTo(PlaybackStateCompat.STATE_PLAYING);
assertThat(playbackStateCompatRef.get().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(controllerCompat.getPlaybackState().getState())
.isEqualTo(PlaybackStateCompat.STATE_PLAYING);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()).isEqualTo(0f);
assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
}
@Test
public void playbackStateChange_playWhenReadyBecomesTrueWhenReady_notifiesPlaying()
throws Exception {
session.getMockPlayer().setPlaybackState(Player.STATE_READY);
session
.getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ false, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
AtomicReference<PlaybackStateCompat> playbackStateCompatRef = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
MediaControllerCompat.Callback callback =
new MediaControllerCompat.Callback() {
@Override
public void onPlaybackStateChanged(PlaybackStateCompat playbackStateCompat) {
playbackStateCompatRef.set(playbackStateCompat);
latch.countDown();
}
};
controllerCompat.registerCallback(callback, handler);
session
.getMockPlayer()
.notifyPlayWhenReadyChanged(
/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateCompatRef.get().getState())
.isEqualTo(PlaybackStateCompat.STATE_PLAYING);
assertThat(playbackStateCompatRef.get().getPlaybackSpeed()).isEqualTo(1f);
assertThat(
playbackStateCompatRef
.get()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
assertThat(controllerCompat.getPlaybackState().getState())
.isEqualTo(PlaybackStateCompat.STATE_PLAYING);
assertThat(controllerCompat.getPlaybackState().getPlaybackSpeed()).isEqualTo(1f);
assertThat(
controllerCompat
.getPlaybackState()
.getExtras()
.getFloat(MediaConstants.EXTRAS_KEY_PLAYBACK_SPEED_COMPAT))
.isEqualTo(1f);
} }
@Test @Test

View File

@ -1818,8 +1818,9 @@ public class MediaControllerListenerTest {
@Test @Test
public void onIsPlayingChanged_isNotified() throws Exception { public void onIsPlayingChanged_isNotified() throws Exception {
boolean testIsPlaying = true; remoteSession
remoteSession.getMockPlayer().notifyIsPlayingChanged(false); .getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
MediaController controller = controllerTestRule.createController(remoteSession.getToken()); MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
AtomicBoolean isPlayingGetterRef = new AtomicBoolean(); AtomicBoolean isPlayingGetterRef = new AtomicBoolean();
@ -1844,18 +1845,17 @@ public class MediaControllerListenerTest {
}; };
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
remoteSession.getMockPlayer().notifyIsPlayingChanged(testIsPlaying); remoteSession.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_READY);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(isPlayingParamRef.get()).isEqualTo(testIsPlaying); assertThat(isPlayingParamRef.get()).isTrue();
assertThat(isPlayingGetterRef.get()).isEqualTo(testIsPlaying); assertThat(isPlayingGetterRef.get()).isTrue();
assertThat(isPlayingOnEventsRef.get()).isEqualTo(testIsPlaying); assertThat(isPlayingOnEventsRef.get()).isTrue();
assertThat(getEventsAsList(eventsRef.get())).containsExactly(Player.EVENT_IS_PLAYING_CHANGED); assertThat(getEventsAsList(eventsRef.get())).contains(Player.EVENT_IS_PLAYING_CHANGED);
} }
@Test @Test
public void onIsPlayingChanged_updatesGetters() throws Exception { public void onIsPlayingChanged_updatesGetters() throws Exception {
boolean testIsPlaying = true;
long testCurrentPositionMs = 11; long testCurrentPositionMs = 11;
long testContentPositionMs = testCurrentPositionMs; // Not playing an ad long testContentPositionMs = testCurrentPositionMs; // Not playing an ad
long testBufferedPositionMs = 100; long testBufferedPositionMs = 100;
@ -1863,7 +1863,9 @@ public class MediaControllerListenerTest {
long testTotalBufferedDurationMs = 120; long testTotalBufferedDurationMs = 120;
long testCurrentLiveOffsetMs = 10; long testCurrentLiveOffsetMs = 10;
long testContentBufferedPositionMs = 240; long testContentBufferedPositionMs = 240;
remoteSession.getMockPlayer().notifyIsPlayingChanged(false); remoteSession
.getMockPlayer()
.setPlayWhenReady(/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
MediaController controller = controllerTestRule.createController(remoteSession.getToken()); MediaController controller = controllerTestRule.createController(remoteSession.getToken());
threadTestRule.getHandler().postAndSync(() -> controller.setTimeDiffMs(/* timeDiff= */ 0L)); threadTestRule.getHandler().postAndSync(() -> controller.setTimeDiffMs(/* timeDiff= */ 0L));
CountDownLatch latch = new CountDownLatch(2); CountDownLatch latch = new CountDownLatch(2);
@ -1906,10 +1908,10 @@ public class MediaControllerListenerTest {
remoteSession.getMockPlayer().setTotalBufferedDuration(testTotalBufferedDurationMs); remoteSession.getMockPlayer().setTotalBufferedDuration(testTotalBufferedDurationMs);
remoteSession.getMockPlayer().setCurrentLiveOffset(testCurrentLiveOffsetMs); remoteSession.getMockPlayer().setCurrentLiveOffset(testCurrentLiveOffsetMs);
remoteSession.getMockPlayer().setContentBufferedPosition(testContentBufferedPositionMs); remoteSession.getMockPlayer().setContentBufferedPosition(testContentBufferedPositionMs);
remoteSession.getMockPlayer().notifyIsPlayingChanged(testIsPlaying); remoteSession.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_READY);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(isPlayingRef.get()).isEqualTo(testIsPlaying); assertThat(isPlayingRef.get()).isEqualTo(true);
assertThat(currentPositionMsRef.get()).isEqualTo(testCurrentPositionMs); assertThat(currentPositionMsRef.get()).isEqualTo(testCurrentPositionMs);
assertThat(contentPositionMsRef.get()).isEqualTo(testContentPositionMs); assertThat(contentPositionMsRef.get()).isEqualTo(testContentPositionMs);
assertThat(bufferedPositionMsRef.get()).isEqualTo(testBufferedPositionMs); assertThat(bufferedPositionMsRef.get()).isEqualTo(testBufferedPositionMs);
@ -1917,7 +1919,7 @@ public class MediaControllerListenerTest {
assertThat(totalBufferedDurationMsRef.get()).isEqualTo(testTotalBufferedDurationMs); assertThat(totalBufferedDurationMsRef.get()).isEqualTo(testTotalBufferedDurationMs);
assertThat(currentLiveOffsetMsRef.get()).isEqualTo(testCurrentLiveOffsetMs); assertThat(currentLiveOffsetMsRef.get()).isEqualTo(testCurrentLiveOffsetMs);
assertThat(contentBufferedPositionMsRef.get()).isEqualTo(testContentBufferedPositionMs); assertThat(contentBufferedPositionMsRef.get()).isEqualTo(testContentBufferedPositionMs);
assertThat(getEventsAsList(eventsRef.get())).containsExactly(Player.EVENT_IS_PLAYING_CHANGED); assertThat(getEventsAsList(eventsRef.get())).contains(Player.EVENT_IS_PLAYING_CHANGED);
} }
@Test @Test

View File

@ -279,7 +279,6 @@ public class MediaControllerTest {
@Player.PlaybackSuppressionReason @Player.PlaybackSuppressionReason
int playbackSuppressionReason = Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS; int playbackSuppressionReason = Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS;
@Player.State int playbackState = Player.STATE_READY; @Player.State int playbackState = Player.STATE_READY;
boolean isPlaying = true;
boolean isLoading = true; boolean isLoading = true;
boolean isShuffleModeEnabled = true; boolean isShuffleModeEnabled = true;
@RepeatMode int repeatMode = Player.REPEAT_MODE_ONE; @RepeatMode int repeatMode = Player.REPEAT_MODE_ONE;
@ -327,7 +326,6 @@ public class MediaControllerTest {
.setPlayWhenReady(playWhenReady) .setPlayWhenReady(playWhenReady)
.setPlaybackSuppressionReason(playbackSuppressionReason) .setPlaybackSuppressionReason(playbackSuppressionReason)
.setPlaybackState(playbackState) .setPlaybackState(playbackState)
.setIsPlaying(isPlaying)
.setIsLoading(isLoading) .setIsLoading(isLoading)
.setShuffleModeEnabled(isShuffleModeEnabled) .setShuffleModeEnabled(isShuffleModeEnabled)
.setRepeatMode(repeatMode) .setRepeatMode(repeatMode)
@ -360,7 +358,6 @@ public class MediaControllerTest {
AtomicBoolean playWhenReadyRef = new AtomicBoolean(); AtomicBoolean playWhenReadyRef = new AtomicBoolean();
AtomicInteger playbackSuppressionReasonRef = new AtomicInteger(); AtomicInteger playbackSuppressionReasonRef = new AtomicInteger();
AtomicInteger playbackStateRef = new AtomicInteger(); AtomicInteger playbackStateRef = new AtomicInteger();
AtomicBoolean isPlayingRef = new AtomicBoolean();
AtomicBoolean isLoadingRef = new AtomicBoolean(); AtomicBoolean isLoadingRef = new AtomicBoolean();
AtomicBoolean isShuffleModeEnabledRef = new AtomicBoolean(); AtomicBoolean isShuffleModeEnabledRef = new AtomicBoolean();
AtomicInteger repeatModeRef = new AtomicInteger(); AtomicInteger repeatModeRef = new AtomicInteger();
@ -393,7 +390,6 @@ public class MediaControllerTest {
playWhenReadyRef.set(controller.getPlayWhenReady()); playWhenReadyRef.set(controller.getPlayWhenReady());
playbackSuppressionReasonRef.set(controller.getPlaybackSuppressionReason()); playbackSuppressionReasonRef.set(controller.getPlaybackSuppressionReason());
playbackStateRef.set(controller.getPlaybackState()); playbackStateRef.set(controller.getPlaybackState());
isPlayingRef.set(controller.isPlaying());
isLoadingRef.set(controller.isLoading()); isLoadingRef.set(controller.isLoading());
isShuffleModeEnabledRef.set(controller.getShuffleModeEnabled()); isShuffleModeEnabledRef.set(controller.getShuffleModeEnabled());
repeatModeRef.set(controller.getRepeatMode()); repeatModeRef.set(controller.getRepeatMode());
@ -423,7 +419,6 @@ public class MediaControllerTest {
assertThat(playWhenReadyRef.get()).isEqualTo(playWhenReady); assertThat(playWhenReadyRef.get()).isEqualTo(playWhenReady);
assertThat(playbackSuppressionReasonRef.get()).isEqualTo(playbackSuppressionReason); assertThat(playbackSuppressionReasonRef.get()).isEqualTo(playbackSuppressionReason);
assertThat(playbackStateRef.get()).isEqualTo(playbackState); assertThat(playbackStateRef.get()).isEqualTo(playbackState);
assertThat(isPlayingRef.get()).isEqualTo(isPlaying);
assertThat(isLoadingRef.get()).isEqualTo(isLoading); assertThat(isLoadingRef.get()).isEqualTo(isLoading);
assertThat(isShuffleModeEnabledRef.get()).isEqualTo(isShuffleModeEnabled); assertThat(isShuffleModeEnabledRef.get()).isEqualTo(isShuffleModeEnabled);
assertThat(repeatModeRef.get()).isEqualTo(repeatMode); assertThat(repeatModeRef.get()).isEqualTo(repeatMode);
@ -842,7 +837,7 @@ public class MediaControllerTest {
long testCurrentPositionMs = 100L; long testCurrentPositionMs = 100L;
Bundle playerConfig = Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder() new RemoteMediaSession.MockPlayerConfigBuilder()
.setIsPlaying(false) .setPlaybackState(Player.STATE_BUFFERING)
.setCurrentPosition(testCurrentPositionMs) .setCurrentPosition(testCurrentPositionMs)
.setDuration(10_000L) .setDuration(10_000L)
.build(); .build();
@ -868,7 +863,8 @@ public class MediaControllerTest {
long testTimeDiff = 50L; long testTimeDiff = 50L;
Bundle playerConfig = Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder() new RemoteMediaSession.MockPlayerConfigBuilder()
.setIsPlaying(true) .setPlaybackState(Player.STATE_READY)
.setPlayWhenReady(true)
.setCurrentPosition(testCurrentPosition) .setCurrentPosition(testCurrentPosition)
.setDuration(10_000L) .setDuration(10_000L)
.setPlaybackParameters(testPlaybackParameters) .setPlaybackParameters(testPlaybackParameters)
@ -897,7 +893,8 @@ public class MediaControllerTest {
new RemoteMediaSession.MockPlayerConfigBuilder() new RemoteMediaSession.MockPlayerConfigBuilder()
.setContentPosition(testContentPosition) .setContentPosition(testContentPosition)
.setDuration(10_000L) .setDuration(10_000L)
.setIsPlaying(true) .setPlaybackState(Player.STATE_READY)
.setPlayWhenReady(true)
.setIsPlayingAd(true) .setIsPlayingAd(true)
.setCurrentAdGroupIndex(0) .setCurrentAdGroupIndex(0)
.setCurrentAdIndexInAdGroup(0) .setCurrentAdIndexInAdGroup(0)
@ -925,7 +922,8 @@ public class MediaControllerTest {
.setCurrentPosition(100L) .setCurrentPosition(100L)
.setContentPosition(100L) // Same as current position b/c not playing an ad .setContentPosition(100L) // Same as current position b/c not playing an ad
.setDuration(10_000L) .setDuration(10_000L)
.setIsPlaying(true) .setPlayWhenReady(true)
.setPlaybackState(Player.STATE_READY)
.setIsPlayingAd(false) .setIsPlayingAd(false)
.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2.0f)) .setPlaybackParameters(new PlaybackParameters(/* speed= */ 2.0f))
.build(); .build();
@ -956,7 +954,8 @@ public class MediaControllerTest {
.setCurrentPosition(10L) .setCurrentPosition(10L)
.setContentPosition(50L) .setContentPosition(50L)
.setDuration(10_000L) .setDuration(10_000L)
.setIsPlaying(true) .setPlayWhenReady(true)
.setPlaybackState(Player.STATE_READY)
.setIsPlayingAd(true) .setIsPlayingAd(true)
.setCurrentAdGroupIndex(0) .setCurrentAdGroupIndex(0)
.setCurrentAdIndexInAdGroup(0) .setCurrentAdIndexInAdGroup(0)

View File

@ -21,6 +21,7 @@ import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assume.assumeTrue;
import android.content.Context; import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
@ -98,8 +99,14 @@ public class MediaSessionKeyEventTest {
// Here's the requirement for an app to receive media key events via MediaSession. // Here's the requirement for an app to receive media key events via MediaSession.
// - SDK < 26: Player should be playing for receiving key events // - SDK < 26: Player should be playing for receiving key events
// - SDK >= 26: Play a media item in the same process of the session for receiving key events. // - SDK >= 26: Play a media item in the same process of the session for receiving key events.
handler.postAndSync(() -> player.notifyIsPlayingChanged(/* isPlaying= */ true)); if (Util.SDK_INT < 26) {
if (Util.SDK_INT >= 26) { handler.postAndSync(
() -> {
player.notifyPlayWhenReadyChanged(
/* playWhenReady= */ true, Player.PLAYBACK_SUPPRESSION_REASON_NONE);
player.notifyPlaybackStateChanged(Player.STATE_READY);
});
} else {
CountDownLatch latch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(1);
handler.postAndSync( handler.postAndSync(
() -> { () -> {
@ -168,6 +175,10 @@ public class MediaSessionKeyEventTest {
@Test @Test
public void playPauseKeyEvent_paused_play() throws Exception { public void playPauseKeyEvent_paused_play() throws Exception {
// We don't receive media key events when we are not playing on API < 26, so we can't test this
// case as it's not supported.
assumeTrue(Util.SDK_INT >= 26);
handler.postAndSync( handler.postAndSync(
() -> { () -> {
player.playbackState = Player.STATE_READY; player.playbackState = Player.STATE_READY;
@ -180,6 +191,10 @@ public class MediaSessionKeyEventTest {
@Test @Test
public void playPauseKeyEvent_fromIdle_prepareAndPlay() throws Exception { public void playPauseKeyEvent_fromIdle_prepareAndPlay() throws Exception {
// We don't receive media key events when we are not playing on API < 26, so we can't test this
// case as it's not supported.
assumeTrue(Util.SDK_INT >= 26);
handler.postAndSync( handler.postAndSync(
() -> { () -> {
player.playbackState = Player.STATE_IDLE; player.playbackState = Player.STATE_IDLE;
@ -193,6 +208,10 @@ public class MediaSessionKeyEventTest {
@Test @Test
public void playPauseKeyEvent_playWhenReadyAndEnded_seekAndPlay() throws Exception { public void playPauseKeyEvent_playWhenReadyAndEnded_seekAndPlay() throws Exception {
// We don't receive media key events when we are not playing on API < 26, so we can't test this
// case as it's not supported.
assumeTrue(Util.SDK_INT >= 26);
handler.postAndSync( handler.postAndSync(
() -> { () -> {
player.playWhenReady = true; player.playWhenReady = true;

View File

@ -36,7 +36,6 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_MUT
import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME;
import static androidx.media3.test.session.common.CommonConstants.KEY_DURATION; import static androidx.media3.test.session.common.CommonConstants.KEY_DURATION;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_LOADING; import static androidx.media3.test.session.common.CommonConstants.KEY_IS_LOADING;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING_AD; import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING_AD;
import static androidx.media3.test.session.common.CommonConstants.KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS; import static androidx.media3.test.session.common.CommonConstants.KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS;
import static androidx.media3.test.session.common.CommonConstants.KEY_MEDIA_METADATA; import static androidx.media3.test.session.common.CommonConstants.KEY_MEDIA_METADATA;
@ -374,7 +373,6 @@ public class MediaSessionProviderService extends Service {
player.playbackSuppressionReason = player.playbackSuppressionReason =
config.getInt(KEY_PLAYBACK_SUPPRESSION_REASON, player.playbackSuppressionReason); config.getInt(KEY_PLAYBACK_SUPPRESSION_REASON, player.playbackSuppressionReason);
player.playbackState = config.getInt(KEY_PLAYBACK_STATE, player.playbackState); player.playbackState = config.getInt(KEY_PLAYBACK_STATE, player.playbackState);
player.isPlaying = config.getBoolean(KEY_IS_PLAYING, player.isPlaying);
player.isLoading = config.getBoolean(KEY_IS_LOADING, player.isLoading); player.isLoading = config.getBoolean(KEY_IS_LOADING, player.isLoading);
player.repeatMode = config.getInt(KEY_REPEAT_MODE, player.repeatMode); player.repeatMode = config.getInt(KEY_REPEAT_MODE, player.repeatMode);
player.shuffleModeEnabled = player.shuffleModeEnabled =
@ -695,16 +693,6 @@ public class MediaSessionProviderService extends Service {
}); });
} }
@Override
public void notifyIsPlayingChanged(String sessionId, boolean isPlaying) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.notifyIsPlayingChanged(isPlaying);
});
}
@Override @Override
public void notifyIsLoadingChanged(String sessionId, boolean isLoading) throws RemoteException { public void notifyIsLoadingChanged(String sessionId, boolean isLoading) throws RemoteException {
runOnHandler( runOnHandler(

View File

@ -245,7 +245,6 @@ public class MockPlayer implements Player {
public boolean playWhenReady; public boolean playWhenReady;
public @PlaybackSuppressionReason int playbackSuppressionReason; public @PlaybackSuppressionReason int playbackSuppressionReason;
public @State int playbackState; public @State int playbackState;
public boolean isPlaying;
public boolean isLoading; public boolean isLoading;
public MediaMetadata mediaMetadata; public MediaMetadata mediaMetadata;
public Commands commands; public Commands commands;
@ -521,6 +520,12 @@ public class MockPlayer implements Player {
} }
} }
/**
* Changes the values returned from {@link #getPlayWhenReady()} and {@link
* #getPlaybackSuppressionReason()}, and triggers {@link Player.Listener#onPlayWhenReadyChanged},
* {@link Player.Listener#onPlaybackSuppressionReasonChanged} or {@link
* Player.Listener#onIsPlayingChanged} as appropriate.
*/
public void notifyPlayWhenReadyChanged( public void notifyPlayWhenReadyChanged(
boolean playWhenReady, @PlayWhenReadyChangeReason int reason) { boolean playWhenReady, @PlayWhenReadyChangeReason int reason) {
boolean playWhenReadyChanged = (this.playWhenReady != playWhenReady); boolean playWhenReadyChanged = (this.playWhenReady != playWhenReady);
@ -529,8 +534,10 @@ public class MockPlayer implements Player {
return; return;
} }
boolean wasPlaying = isPlaying();
this.playWhenReady = playWhenReady; this.playWhenReady = playWhenReady;
this.playbackSuppressionReason = reason; this.playbackSuppressionReason = reason;
boolean isPlaying = isPlaying();
for (Listener listener : listeners) { for (Listener listener : listeners) {
if (playWhenReadyChanged) { if (playWhenReadyChanged) {
listener.onPlayWhenReadyChanged( listener.onPlayWhenReadyChanged(
@ -539,26 +546,29 @@ public class MockPlayer implements Player {
if (playbackSuppressionReasonChanged) { if (playbackSuppressionReasonChanged) {
listener.onPlaybackSuppressionReasonChanged(reason); listener.onPlaybackSuppressionReasonChanged(reason);
} }
if (isPlaying != wasPlaying) {
listener.onIsPlayingChanged(isPlaying);
}
} }
} }
/**
* Changes the value returned from {@link #getPlaybackState()} and triggers {@link
* Player.Listener#onPlaybackStateChanged} and/or {@link Player.Listener#onIsPlayingChanged} as
* appropriate.
*/
public void notifyPlaybackStateChanged(@State int playbackState) { public void notifyPlaybackStateChanged(@State int playbackState) {
if (this.playbackState == playbackState) { if (this.playbackState == playbackState) {
return; return;
} }
boolean wasPlaying = isPlaying();
this.playbackState = playbackState; this.playbackState = playbackState;
boolean isPlaying = isPlaying();
for (Listener listener : listeners) { for (Listener listener : listeners) {
listener.onPlaybackStateChanged(playbackState); listener.onPlaybackStateChanged(playbackState);
} if (isPlaying != wasPlaying) {
} listener.onIsPlayingChanged(isPlaying);
}
public void notifyIsPlayingChanged(boolean isPlaying) {
if (this.isPlaying == isPlaying) {
return;
}
this.isPlaying = isPlaying;
for (Listener listener : listeners) {
listener.onIsPlayingChanged(isPlaying);
} }
} }
@ -698,7 +708,9 @@ public class MockPlayer implements Player {
@Override @Override
public boolean isPlaying() { public boolean isPlaying() {
return isPlaying; return playWhenReady
&& playbackState == Player.STATE_READY
&& playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE;
} }
@Override @Override

View File

@ -35,7 +35,6 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_MUT
import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME;
import static androidx.media3.test.session.common.CommonConstants.KEY_DURATION; import static androidx.media3.test.session.common.CommonConstants.KEY_DURATION;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_LOADING; import static androidx.media3.test.session.common.CommonConstants.KEY_IS_LOADING;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING;
import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING_AD; import static androidx.media3.test.session.common.CommonConstants.KEY_IS_PLAYING_AD;
import static androidx.media3.test.session.common.CommonConstants.KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS; import static androidx.media3.test.session.common.CommonConstants.KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS;
import static androidx.media3.test.session.common.CommonConstants.KEY_MEDIA_METADATA; import static androidx.media3.test.session.common.CommonConstants.KEY_MEDIA_METADATA;
@ -296,10 +295,6 @@ public class RemoteMediaSession {
binder.notifyPlaybackStateChanged(sessionId, state); binder.notifyPlaybackStateChanged(sessionId, state);
} }
public void notifyIsPlayingChanged(boolean isPlaying) throws RemoteException {
binder.notifyIsPlayingChanged(sessionId, isPlaying);
}
public void notifyIsLoadingChanged(boolean isLoading) throws RemoteException { public void notifyIsLoadingChanged(boolean isLoading) throws RemoteException {
binder.notifyIsLoadingChanged(sessionId, isLoading); binder.notifyIsLoadingChanged(sessionId, isLoading);
} }
@ -687,12 +682,6 @@ public class RemoteMediaSession {
return this; return this;
} }
@CanIgnoreReturnValue
public MockPlayerConfigBuilder setIsPlaying(boolean isPlaying) {
bundle.putBoolean(KEY_IS_PLAYING, isPlaying);
return this;
}
@CanIgnoreReturnValue @CanIgnoreReturnValue
public MockPlayerConfigBuilder setIsLoading(boolean isLoading) { public MockPlayerConfigBuilder setIsLoading(boolean isLoading) {
bundle.putBoolean(KEY_IS_LOADING, isLoading); bundle.putBoolean(KEY_IS_LOADING, isLoading);