mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Clear one-off events from state as soon as they are triggered.
This ensures they are not accidentally triggered again when the state is rebuilt with a buildUpon method. PiperOrigin-RevId: 495280711
This commit is contained in:
parent
21ae403049
commit
a123134892
@ -2888,6 +2888,15 @@ public abstract class SimpleBasePlayer extends BasePlayer {
|
|||||||
// Assign new state immediately such that all getters return the right values, but use a
|
// Assign new state immediately such that all getters return the right values, but use a
|
||||||
// snapshot of the previous and new state so that listener invocations are triggered correctly.
|
// snapshot of the previous and new state so that listener invocations are triggered correctly.
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
|
if (newState.hasPositionDiscontinuity || newState.newlyRenderedFirstFrame) {
|
||||||
|
// Clear one-time events to avoid signalling them again later.
|
||||||
|
this.state =
|
||||||
|
this.state
|
||||||
|
.buildUpon()
|
||||||
|
.clearPositionDiscontinuity()
|
||||||
|
.setNewlyRenderedFirstFrame(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
boolean playWhenReadyChanged = previousState.playWhenReady != newState.playWhenReady;
|
boolean playWhenReadyChanged = previousState.playWhenReady != newState.playWhenReady;
|
||||||
boolean playbackStateChanged = previousState.playbackState != newState.playbackState;
|
boolean playbackStateChanged = previousState.playbackState != newState.playbackState;
|
||||||
@ -2914,7 +2923,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
|
|||||||
PositionInfo positionInfo =
|
PositionInfo positionInfo =
|
||||||
getPositionInfo(
|
getPositionInfo(
|
||||||
newState,
|
newState,
|
||||||
/* useDiscontinuityPosition= */ state.hasPositionDiscontinuity,
|
/* useDiscontinuityPosition= */ newState.hasPositionDiscontinuity,
|
||||||
window,
|
window,
|
||||||
period);
|
period);
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
@ -2928,9 +2937,9 @@ public abstract class SimpleBasePlayer extends BasePlayer {
|
|||||||
if (mediaItemTransitionReason != C.INDEX_UNSET) {
|
if (mediaItemTransitionReason != C.INDEX_UNSET) {
|
||||||
@Nullable
|
@Nullable
|
||||||
MediaItem mediaItem =
|
MediaItem mediaItem =
|
||||||
state.timeline.isEmpty()
|
newState.timeline.isEmpty()
|
||||||
? null
|
? null
|
||||||
: state.playlist.get(state.currentMediaItemIndex).mediaItem;
|
: newState.playlist.get(state.currentMediaItemIndex).mediaItem;
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||||
listener -> listener.onMediaItemTransition(mediaItem, mediaItemTransitionReason));
|
listener -> listener.onMediaItemTransition(mediaItem, mediaItemTransitionReason));
|
||||||
|
@ -1697,6 +1697,82 @@ public class SimpleBasePlayerTest {
|
|||||||
verify(listener, never()).onMediaItemTransition(any(), anyInt());
|
verify(listener, never()).onMediaItemTransition(any(), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Verifying deprecated listener call.
|
||||||
|
@Test
|
||||||
|
public void invalidateStateAndOtherOperation_withDiscontinuity_reportsDiscontinuityOnlyOnce() {
|
||||||
|
State state =
|
||||||
|
new State.Builder()
|
||||||
|
.setAvailableCommands(new Commands.Builder().addAllCommands().build())
|
||||||
|
.setPlaylist(
|
||||||
|
ImmutableList.of(new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0).build()))
|
||||||
|
.setPositionDiscontinuity(
|
||||||
|
Player.DISCONTINUITY_REASON_INTERNAL, /* discontinuityPositionMs= */ 2000)
|
||||||
|
.build();
|
||||||
|
SimpleBasePlayer player =
|
||||||
|
new SimpleBasePlayer(Looper.myLooper()) {
|
||||||
|
@Override
|
||||||
|
protected State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ListenableFuture<?> handlePrepare() {
|
||||||
|
// We just care about the placeholder state, so return an unfulfilled future.
|
||||||
|
return SettableFuture.create();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Listener listener = mock(Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.invalidateState();
|
||||||
|
player.prepare();
|
||||||
|
|
||||||
|
// Assert listener calls (in particular getting only a single discontinuity).
|
||||||
|
verify(listener)
|
||||||
|
.onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_INTERNAL));
|
||||||
|
verify(listener).onPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
|
verify(listener).onPlaybackStateChanged(Player.STATE_BUFFERING);
|
||||||
|
verify(listener).onPlayerStateChanged(/* playWhenReady= */ false, Player.STATE_BUFFERING);
|
||||||
|
verifyNoMoreInteractions(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Verifying deprecated listener call.
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
invalidateStateAndOtherOperation_withRenderedFirstFrame_reportsRenderedFirstFrameOnlyOnce() {
|
||||||
|
State state =
|
||||||
|
new State.Builder()
|
||||||
|
.setAvailableCommands(new Commands.Builder().addAllCommands().build())
|
||||||
|
.setPlaylist(
|
||||||
|
ImmutableList.of(new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0).build()))
|
||||||
|
.setNewlyRenderedFirstFrame(true)
|
||||||
|
.build();
|
||||||
|
SimpleBasePlayer player =
|
||||||
|
new SimpleBasePlayer(Looper.myLooper()) {
|
||||||
|
@Override
|
||||||
|
protected State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ListenableFuture<?> handlePrepare() {
|
||||||
|
// We just care about the placeholder state, so return an unfulfilled future.
|
||||||
|
return SettableFuture.create();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Listener listener = mock(Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.invalidateState();
|
||||||
|
player.prepare();
|
||||||
|
|
||||||
|
// Assert listener calls (in particular getting only a single rendered first frame).
|
||||||
|
verify(listener).onRenderedFirstFrame();
|
||||||
|
verify(listener).onPlaybackStateChanged(Player.STATE_BUFFERING);
|
||||||
|
verify(listener).onPlayerStateChanged(/* playWhenReady= */ false, Player.STATE_BUFFERING);
|
||||||
|
verifyNoMoreInteractions(listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void invalidateState_duringAsyncMethodHandling_isIgnored() {
|
public void invalidateState_duringAsyncMethodHandling_isIgnored() {
|
||||||
State state1 =
|
State state1 =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user