Avoid resetting suppression reason with play/pause on MediaController

Unlike ExoPlayer, when play/pause is called on MediaController, the playback suppression reason is set to default causing a change in it and subsequent callbacks on the Player.Listener.

PiperOrigin-RevId: 548088931
This commit is contained in:
Googler 2023-07-14 12:29:38 +01:00 committed by Ian Baker
parent 847f6f24d3
commit 46482e0384
2 changed files with 109 additions and 17 deletions

View File

@ -393,10 +393,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.play(controllerStub, seq));
setPlayWhenReady(
/* playWhenReady= */ true,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
setPlayWhenReady(/* playWhenReady= */ true, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
}
@Override
@ -408,10 +405,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.pause(controllerStub, seq));
setPlayWhenReady(
/* playWhenReady= */ false,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
setPlayWhenReady(/* playWhenReady= */ false, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
}
@Override
@ -533,10 +527,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.setPlayWhenReady(controllerStub, seq, playWhenReady));
setPlayWhenReady(
playWhenReady,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
setPlayWhenReady(playWhenReady, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
}
@Override
@ -2154,11 +2145,15 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
private void setPlayWhenReady(
boolean playWhenReady,
@Player.PlaybackSuppressionReason int playbackSuppressionReason,
@Player.PlayWhenReadyChangeReason int playWhenReadyChangeReason) {
boolean playWhenReady, @Player.PlayWhenReadyChangeReason int playWhenReadyChangeReason) {
// Transient audio focus loss will be resolved by requesting focus again, so eagerly remove it
// here in the masked value.
@Player.PlaybackSuppressionReason int maskedSuppressionReason = getPlaybackSuppressionReason();
if (maskedSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS) {
maskedSuppressionReason = Player.PLAYBACK_SUPPRESSION_REASON_NONE;
}
if (playerInfo.playWhenReady == playWhenReady
&& playerInfo.playbackSuppressionReason == playbackSuppressionReason) {
&& playerInfo.playbackSuppressionReason == maskedSuppressionReason) {
return;
}
@ -2167,7 +2162,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
lastSetPlayWhenReadyCalledTimeMs = SystemClock.elapsedRealtime();
PlayerInfo newPlayerInfo =
this.playerInfo.copyWithPlayWhenReady(
playWhenReady, playWhenReadyChangeReason, playbackSuppressionReason);
playWhenReady, playWhenReadyChangeReason, maskedSuppressionReason);
updatePlayerInfo(
newPlayerInfo,
/* timelineChangeReason= */ null,

View File

@ -170,6 +170,103 @@ public class MediaControllerStateMaskingTest {
assertThat(isPlayingFromGetterRef.get()).isEqualTo(testIsPlaying);
}
@Test
public void setPlayWhenReady_forTrueWhenPlaybackSuppressed_shouldNotChangePlaybackSuppression()
throws Exception {
CountDownLatch eventCallsCountDownLatch = new CountDownLatch(1);
AtomicReference<@Player.PlaybackSuppressionReason Integer> playbackSuppressionReasonChangedRef =
new AtomicReference<>();
AtomicReference<Player.Events> eventsRef = new AtomicReference<>();
MediaController controller =
getMediaControllerToTestPlaybackSuppression(
/* initialPlayWhenReadyState= */ false,
playbackSuppressionReasonChangedRef,
eventsRef,
eventCallsCountDownLatch);
threadTestRule.getHandler().postAndSync(() -> controller.setPlayWhenReady(true));
assertNoPlaybackSuppressionReasonChange(
playbackSuppressionReasonChangedRef, eventsRef, eventCallsCountDownLatch);
}
@Test
public void setPlayWhenReady_withFalseWhenPlaybackSuppressed_shouldNotChangePlaybackSuppression()
throws Exception {
CountDownLatch eventCallsCountDownLatch = new CountDownLatch(1);
AtomicReference<@Player.PlaybackSuppressionReason Integer> playbackSuppressionReasonChangedRef =
new AtomicReference<>();
AtomicReference<Player.Events> eventsRef = new AtomicReference<>();
MediaController controller =
getMediaControllerToTestPlaybackSuppression(
/* initialPlayWhenReadyState= */ true,
playbackSuppressionReasonChangedRef,
eventsRef,
eventCallsCountDownLatch);
threadTestRule.getHandler().postAndSync(() -> controller.setPlayWhenReady(false));
assertNoPlaybackSuppressionReasonChange(
playbackSuppressionReasonChangedRef, eventsRef, eventCallsCountDownLatch);
}
private MediaController getMediaControllerToTestPlaybackSuppression(
boolean initialPlayWhenReadyState,
AtomicReference<@Player.PlaybackSuppressionReason Integer>
playbackSuppressionReasonChangedRef,
AtomicReference<Player.Events> eventsRef,
CountDownLatch countDownLatchForOnEventCalls)
throws Exception {
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder()
.setPlaybackState(Player.STATE_READY)
.setPlayWhenReady(initialPlayWhenReadyState)
.setPlaybackSuppressionReason(
Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_OUTPUT)
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
threadTestRule
.getHandler()
.postAndSync(
() ->
controller.addListener(
getPlayerListenerToCapturePlaybackSuppression(
playbackSuppressionReasonChangedRef,
eventsRef,
countDownLatchForOnEventCalls)));
return controller;
}
private Player.Listener getPlayerListenerToCapturePlaybackSuppression(
AtomicReference<@Player.PlaybackSuppressionReason Integer>
playbackSuppressionReasonChangedRef,
AtomicReference<Player.Events> eventsRef,
CountDownLatch countDownLatchForOnEventCalls) {
return new Player.Listener() {
@Override
public void onEvents(Player player, Player.Events events) {
eventsRef.set(events);
if (events.contains(Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED)) {
playbackSuppressionReasonChangedRef.set(player.getPlaybackSuppressionReason());
}
countDownLatchForOnEventCalls.countDown();
}
};
}
private void assertNoPlaybackSuppressionReasonChange(
AtomicReference<@Player.PlaybackSuppressionReason Integer>
playbackSuppressionReasonChangedRef,
AtomicReference<Player.Events> eventsRef,
CountDownLatch countDownLatchForOnEventCalls)
throws Exception {
assertThat(countDownLatchForOnEventCalls.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackSuppressionReasonChangedRef.get()).isNull();
assertThat(eventsRef.get().contains(Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED))
.isFalse();
}
@Test
public void setShuffleModeEnabled() throws Exception {
boolean testShuffleModeEnabled = true;