Do not override pending info when masking

PiperOrigin-RevId: 712919739
This commit is contained in:
bachinger 2025-01-07 08:23:10 -08:00 committed by Copybara-Service
parent e11aabb794
commit ec50358784
3 changed files with 57 additions and 1 deletions

View file

@ -40,6 +40,9 @@
in both `Mp4Muxer.Builder` and `FragmentedMp4Muxer.Builder`. in both `Mp4Muxer.Builder` and `FragmentedMp4Muxer.Builder`.
* IMA extension: * IMA extension:
* Session: * Session:
* Fix bug where calling a `Player` method on a `MediaController` connected
to a legacy session dropped changes of a pending update coming from the
legacy session.
* UI: * UI:
* Add `PresentationState` state holder class and the corresponding * Add `PresentationState` state holder class and the corresponding
`rememberPresentationState` Composable to `media3-ui-compose`. `rememberPresentationState` Composable to `media3-ui-compose`.

View file

@ -1593,6 +1593,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
updateControllerInfo( updateControllerInfo(
notifyConnected, notifyConnected,
newLegacyPlayerInfo, newLegacyPlayerInfo,
/* resetPendingLegacyPlayerInfo= */ true,
newControllerInfo, newControllerInfo,
/* discontinuityReason= */ reasons.first, /* discontinuityReason= */ reasons.first,
/* mediaItemTransitionReason= */ reasons.second); /* mediaItemTransitionReason= */ reasons.second);
@ -1616,6 +1617,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
updateControllerInfo( updateControllerInfo(
/* notifyConnected= */ false, /* notifyConnected= */ false,
legacyPlayerInfo, legacyPlayerInfo,
/* resetPendingLegacyPlayerInfo= */ false,
newControllerInfo, newControllerInfo,
discontinuityReason, discontinuityReason,
mediaItemTransitionReason); mediaItemTransitionReason);
@ -1626,6 +1628,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
private void updateControllerInfo( private void updateControllerInfo(
boolean notifyConnected, boolean notifyConnected,
LegacyPlayerInfo newLegacyPlayerInfo, LegacyPlayerInfo newLegacyPlayerInfo,
boolean resetPendingLegacyPlayerInfo,
ControllerInfo newControllerInfo, ControllerInfo newControllerInfo,
@Nullable @Player.DiscontinuityReason Integer discontinuityReason, @Nullable @Player.DiscontinuityReason Integer discontinuityReason,
@Nullable @Player.MediaItemTransitionReason Integer mediaItemTransitionReason) { @Nullable @Player.MediaItemTransitionReason Integer mediaItemTransitionReason) {
@ -1634,7 +1637,9 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization;
if (legacyPlayerInfo != newLegacyPlayerInfo) { if (legacyPlayerInfo != newLegacyPlayerInfo) {
legacyPlayerInfo = new LegacyPlayerInfo(newLegacyPlayerInfo); legacyPlayerInfo = new LegacyPlayerInfo(newLegacyPlayerInfo);
} }
pendingLegacyPlayerInfo = legacyPlayerInfo; if (resetPendingLegacyPlayerInfo) {
pendingLegacyPlayerInfo = legacyPlayerInfo;
}
controllerInfo = newControllerInfo; controllerInfo = newControllerInfo;
if (notifyConnected) { if (notifyConnected) {

View file

@ -38,6 +38,7 @@ import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player; import androidx.media3.common.Player;
import androidx.media3.common.util.ConditionVariable; import androidx.media3.common.util.ConditionVariable;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.session.legacy.MediaMetadataCompat;
import androidx.media3.test.session.R; import androidx.media3.test.session.R;
import androidx.media3.test.session.common.CommonConstants; import androidx.media3.test.session.common.CommonConstants;
import androidx.media3.test.session.common.HandlerThreadTestRule; import androidx.media3.test.session.common.HandlerThreadTestRule;
@ -818,4 +819,51 @@ public class MediaControllerListenerWithMediaSessionCompatTest {
assertThat(threadTestRule.getHandler().postAndSync(controller::getCurrentPosition)) assertThat(threadTestRule.getHandler().postAndSync(controller::getCurrentPosition))
.isEqualTo(0); .isEqualTo(0);
} }
@SuppressWarnings("deprecation") // Testing interoperability and backwards compatibility.
@Test
public void setDeviceVolume_whenWaitingForPendingUpdates_maskingDoesNotOverridePendingUpdate()
throws Exception {
MediaController controller = controllerTestRule.createController(session.getSessionToken());
List<Integer> reportedPlaybackStates = new ArrayList<>();
List<MediaMetadata> reportedMediaMetadata = new ArrayList<>();
ConditionVariable playbackStateChanged = new ConditionVariable();
ConditionVariable mediaMetadataChanged = new ConditionVariable();
playbackStateChanged.close();
controller.addListener(
new Player.Listener() {
@Override
public void onPlaybackStateChanged(int playbackState) {
reportedPlaybackStates.add(playbackState);
playbackStateChanged.open();
}
@Override
public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {
reportedMediaMetadata.add(mediaMetadata);
mediaMetadataChanged.open();
}
});
session.setMetadata(
new android.support.v4.media.MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "artist-0")
.build());
session.setPlaybackState(
new PlaybackStateCompat.Builder()
.setState(
PlaybackStateCompat.STATE_PLAYING, /* position= */ 1001L, /* playbackSpeed= */ 1.0f)
.build());
synchronized (this) {
// Wait 200ms to make playback state and metadata arrive.
Thread.sleep(200);
// Trigger masking than must not drop the pending legacy info.
threadTestRule.getHandler().postAndSync(() -> controller.setDeviceVolume(1, 0));
}
assertThat(playbackStateChanged.block(TIMEOUT_MS)).isTrue();
assertThat(mediaMetadataChanged.block(TIMEOUT_MS)).isTrue();
assertThat(reportedPlaybackStates).containsExactly(3);
assertThat(reportedMediaMetadata.stream().map((m) -> m.artist)).containsExactly("artist-0");
}
} }