MediaController: Add missing event flags (1/2)

This is the first commit out of two. This change adds the missing event
flags for the onEvents() callback when MediaController is connected to a
media3 session (see MediaControllerImplBase). I updated the
MediaControllerListenerTest and MediaControllerStateMaskingTest with
assertions that on onEvents() is called alongside individual
Player.Listener callbacks.

There will be a follow-up change for the case where a MediaController is
connected to a legacy MediaSession (MediaControllerImplLegacy). I've
split this in two separate changes to make the size of the commit
manageable for reviewing.

#minor-release

PiperOrigin-RevId: 481933437
(cherry picked from commit 46d5a0e33bd562cd9e6420b342a68bf112847f83)
This commit is contained in:
christosts 2022-10-18 15:54:54 +00:00 committed by microkatz
parent e589718414
commit ba84c2a09c
9 changed files with 1267 additions and 374 deletions

View File

@ -240,7 +240,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo.copyWithPlaybackState(
Player.STATE_IDLE, /* playerError= */ playerInfo.playerError);
listeners.queueEvent(
Player.EVENT_PLAYBACK_STATE_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(Player.STATE_IDLE));
listeners.flushEvents();
}
@ -698,7 +698,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo = playerInfo.copyWithPlaybackParameters(playbackParameters);
listeners.queueEvent(
Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(playbackParameters));
listeners.flushEvents();
}
@ -724,7 +724,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo = playerInfo.copyWithPlaybackParameters(newPlaybackParameters);
listeners.queueEvent(
Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(newPlaybackParameters));
listeners.flushEvents();
}
@ -902,10 +902,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (!playerInfo.playlistMetadata.equals(playlistMetadata)) {
playerInfo = playerInfo.copyWithPlaylistMetadata(playlistMetadata);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_PLAYLIST_METADATA_CHANGED,
listener -> listener.onPlaylistMetadataChanged(playlistMetadata));
listeners.flushEvents();
}
@ -1404,7 +1402,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo = playerInfo.copyWithRepeatMode(repeatMode);
listeners.queueEvent(
Player.EVENT_REPEAT_MODE_CHANGED, listener -> listener.onRepeatModeChanged(repeatMode));
/* eventFlag= */ Player.EVENT_REPEAT_MODE_CHANGED,
listener -> listener.onRepeatModeChanged(repeatMode));
listeners.flushEvents();
}
}
@ -1433,7 +1432,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo = playerInfo.copyWithShuffleModeEnabled(shuffleModeEnabled);
listeners.queueEvent(
Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
/* eventFlag= */ Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(shuffleModeEnabled));
listeners.flushEvents();
}
@ -1461,10 +1460,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (playerInfo.volume != volume) {
playerInfo = playerInfo.copyWithVolume(volume);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onVolumeChanged(volume));
/* eventFlag= */ Player.EVENT_VOLUME_CHANGED,
listener -> listener.onVolumeChanged(volume));
listeners.flushEvents();
}
}
@ -1497,9 +1495,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (playerInfo.deviceVolume != volume) {
playerInfo = playerInfo.copyWithDeviceVolume(volume, playerInfo.deviceMuted);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(volume, playerInfo.deviceMuted));
listeners.flushEvents();
}
@ -1518,10 +1515,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
int newDeviceVolume = playerInfo.deviceVolume + 1;
if (newDeviceVolume <= getDeviceInfo().maxVolume) {
playerInfo = playerInfo.copyWithDeviceVolume(newDeviceVolume, playerInfo.deviceMuted);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(newDeviceVolume, playerInfo.deviceMuted));
listeners.flushEvents();
}
@ -1540,10 +1535,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
int newDeviceVolume = playerInfo.deviceVolume - 1;
if (newDeviceVolume >= getDeviceInfo().minVolume) {
playerInfo = playerInfo.copyWithDeviceVolume(newDeviceVolume, playerInfo.deviceMuted);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(newDeviceVolume, playerInfo.deviceMuted));
listeners.flushEvents();
}
@ -1561,10 +1554,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (playerInfo.deviceMuted != muted) {
playerInfo = playerInfo.copyWithDeviceVolume(playerInfo.deviceVolume, muted);
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(playerInfo.deviceVolume, muted));
listeners.flushEvents();
}
@ -1751,7 +1742,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
playerInfo = playerInfo.copyWithTrackSelectionParameters(parameters);
listeners.queueEvent(
Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
/* eventFlag= */ Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
listener -> listener.onTrackSelectionParametersChanged(parameters));
listeners.flushEvents();
}
@ -2074,14 +2065,14 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (mediaItemTransition) {
listeners.queueEvent(
Player.EVENT_MEDIA_ITEM_TRANSITION,
/* eventFlag= */ Player.EVENT_MEDIA_ITEM_TRANSITION,
listener ->
listener.onMediaItemTransition(
newPlayerInfo.getCurrentMediaItem(), mediaItemTransitionReason));
}
if (positionDiscontinuity) {
listeners.queueEvent(
Player.EVENT_POSITION_DISCONTINUITY,
/* eventFlag= */ Player.EVENT_POSITION_DISCONTINUITY,
listener ->
listener.onPositionDiscontinuity(
newPlayerInfo.oldPositionInfo,
@ -2090,30 +2081,30 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
if (!oldPlayerInfo.timeline.equals(newPlayerInfo.timeline)) {
listeners.queueEvent(
Player.EVENT_TIMELINE_CHANGED,
/* eventFlag= */ Player.EVENT_TIMELINE_CHANGED,
listener -> listener.onTimelineChanged(newPlayerInfo.timeline, timelineChangeReason));
}
if (oldPlayerInfo.playbackState != newPlayerInfo.playbackState) {
listeners.queueEvent(
Player.EVENT_PLAYBACK_STATE_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(newPlayerInfo.playbackState));
}
if (oldPlayerInfo.playWhenReady != newPlayerInfo.playWhenReady) {
listeners.queueEvent(
Player.EVENT_PLAY_WHEN_READY_CHANGED,
/* eventFlag= */ Player.EVENT_PLAY_WHEN_READY_CHANGED,
listener ->
listener.onPlayWhenReadyChanged(
newPlayerInfo.playWhenReady, playWhenReadyChangeReason));
}
if (oldPlayerInfo.playbackSuppressionReason != newPlayerInfo.playbackSuppressionReason) {
listeners.queueEvent(
Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
listener ->
listener.onPlaybackSuppressionReasonChanged(newPlayerInfo.playbackSuppressionReason));
}
if (oldPlayerInfo.isPlaying != newPlayerInfo.isPlaying) {
listeners.queueEvent(
Player.EVENT_IS_PLAYING_CHANGED,
/* eventFlag= */ Player.EVENT_IS_PLAYING_CHANGED,
listener -> listener.onIsPlayingChanged(newPlayerInfo.isPlaying));
}
listeners.flushEvents();
@ -2201,10 +2192,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (surfaceWidth != width || surfaceHeight != height) {
surfaceWidth = width;
surfaceHeight = height;
// TODO(b/187152483): Set proper event code when available.
listeners.sendEvent(
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSurfaceSizeChanged(width, height));
/* eventFlag= */ Player.EVENT_SURFACE_SIZE_CHANGED,
listener -> listener.onSurfaceSizeChanged(width, height));
}
}
@ -2341,123 +2331,119 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|| (oldPlayerError != null && oldPlayerError.errorInfoEquals(playerError));
if (!errorsMatch) {
listeners.queueEvent(
Player.EVENT_PLAYER_ERROR,
/* eventFlag= */ Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerErrorChanged(playerInfo.playerError));
if (playerInfo.playerError != null) {
listeners.queueEvent(
Player.EVENT_PLAYER_ERROR, listener -> listener.onPlayerError(playerInfo.playerError));
/* eventFlag= */ Player.EVENT_PLAYER_ERROR,
listener -> listener.onPlayerError(playerInfo.playerError));
}
}
MediaItem oldCurrentMediaItem = oldPlayerInfo.getCurrentMediaItem();
MediaItem currentMediaItem = playerInfo.getCurrentMediaItem();
if (!Util.areEqual(oldCurrentMediaItem, currentMediaItem)) {
listeners.queueEvent(
Player.EVENT_MEDIA_ITEM_TRANSITION,
/* eventFlag= */ Player.EVENT_MEDIA_ITEM_TRANSITION,
listener ->
listener.onMediaItemTransition(
currentMediaItem, playerInfo.mediaItemTransitionReason));
}
if (!Util.areEqual(oldPlayerInfo.currentTracks, playerInfo.currentTracks)) {
listeners.queueEvent(
Player.EVENT_TRACKS_CHANGED,
/* eventFlag= */ Player.EVENT_TRACKS_CHANGED,
listener -> listener.onTracksChanged(playerInfo.currentTracks));
}
if (!Util.areEqual(oldPlayerInfo.playbackParameters, playerInfo.playbackParameters)) {
listeners.queueEvent(
Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_PARAMETERS_CHANGED,
listener -> listener.onPlaybackParametersChanged(playerInfo.playbackParameters));
}
if (oldPlayerInfo.repeatMode != playerInfo.repeatMode) {
listeners.queueEvent(
Player.EVENT_REPEAT_MODE_CHANGED,
/* eventFlag= */ Player.EVENT_REPEAT_MODE_CHANGED,
listener -> listener.onRepeatModeChanged(playerInfo.repeatMode));
}
if (oldPlayerInfo.shuffleModeEnabled != playerInfo.shuffleModeEnabled) {
listeners.queueEvent(
Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
/* eventFlag= */ Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(playerInfo.shuffleModeEnabled));
}
if (!isTimelineExcluded && !Util.areEqual(oldPlayerInfo.timeline, playerInfo.timeline)) {
listeners.queueEvent(
Player.EVENT_TIMELINE_CHANGED,
/* eventFlag= */ Player.EVENT_TIMELINE_CHANGED,
listener -> listener.onTimelineChanged(playerInfo.timeline, timelineChangedReason));
}
if (!Util.areEqual(oldPlayerInfo.playlistMetadata, playerInfo.playlistMetadata)) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_PLAYLIST_METADATA_CHANGED,
listener -> listener.onPlaylistMetadataChanged(playerInfo.playlistMetadata));
}
if (oldPlayerInfo.volume != playerInfo.volume) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onVolumeChanged(playerInfo.volume));
/* eventFlag= */ Player.EVENT_VOLUME_CHANGED,
listener -> listener.onVolumeChanged(playerInfo.volume));
}
if (!Util.areEqual(oldPlayerInfo.audioAttributes, playerInfo.audioAttributes)) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_AUDIO_ATTRIBUTES_CHANGED,
listener -> listener.onAudioAttributesChanged(playerInfo.audioAttributes));
}
if (!oldPlayerInfo.cueGroup.cues.equals(playerInfo.cueGroup.cues)) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onCues(playerInfo.cueGroup.cues));
/* eventFlag= */ Player.EVENT_CUES,
listener -> listener.onCues(playerInfo.cueGroup.cues));
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onCues(playerInfo.cueGroup));
/* eventFlag= */ Player.EVENT_CUES, listener -> listener.onCues(playerInfo.cueGroup));
}
if (!Util.areEqual(oldPlayerInfo.deviceInfo, playerInfo.deviceInfo)) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_INFO_CHANGED,
listener -> listener.onDeviceInfoChanged(playerInfo.deviceInfo));
}
if (oldPlayerInfo.deviceVolume != playerInfo.deviceVolume
|| oldPlayerInfo.deviceMuted != playerInfo.deviceMuted) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener ->
listener.onDeviceVolumeChanged(playerInfo.deviceVolume, playerInfo.deviceMuted));
}
if (oldPlayerInfo.playWhenReady != playerInfo.playWhenReady) {
listeners.queueEvent(
Player.EVENT_PLAY_WHEN_READY_CHANGED,
/* eventFlag= */ Player.EVENT_PLAY_WHEN_READY_CHANGED,
listener ->
listener.onPlayWhenReadyChanged(
playerInfo.playWhenReady, playerInfo.playWhenReadyChangedReason));
}
if (oldPlayerInfo.playbackSuppressionReason != playerInfo.playbackSuppressionReason) {
listeners.queueEvent(
Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
listener ->
listener.onPlaybackSuppressionReasonChanged(playerInfo.playbackSuppressionReason));
}
if (oldPlayerInfo.playbackState != playerInfo.playbackState) {
listeners.queueEvent(
Player.EVENT_PLAYBACK_STATE_CHANGED,
/* eventFlag= */ Player.EVENT_PLAYBACK_STATE_CHANGED,
listener -> listener.onPlaybackStateChanged(playerInfo.playbackState));
}
if (oldPlayerInfo.isPlaying != playerInfo.isPlaying) {
listeners.queueEvent(
Player.EVENT_IS_PLAYING_CHANGED,
/* eventFlag= */ Player.EVENT_IS_PLAYING_CHANGED,
listener -> listener.onIsPlayingChanged(playerInfo.isPlaying));
}
if (oldPlayerInfo.isLoading != playerInfo.isLoading) {
listeners.queueEvent(
Player.EVENT_IS_LOADING_CHANGED,
/* eventFlag= */ Player.EVENT_IS_LOADING_CHANGED,
listener -> listener.onIsLoadingChanged(playerInfo.isLoading));
}
if (!Util.areEqual(oldPlayerInfo.videoSize, playerInfo.videoSize)) {
// TODO(b/187152483): Set proper event code when available.
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
/* eventFlag= */ Player.EVENT_VIDEO_SIZE_CHANGED,
listener -> listener.onVideoSizeChanged(playerInfo.videoSize));
}
if (!Util.areEqual(oldPlayerInfo.oldPositionInfo, playerInfo.oldPositionInfo)
|| !Util.areEqual(oldPlayerInfo.newPositionInfo, playerInfo.newPositionInfo)) {
listeners.queueEvent(
Player.EVENT_POSITION_DISCONTINUITY,
/* eventFlag= */ Player.EVENT_POSITION_DISCONTINUITY,
listener ->
listener.onPositionDiscontinuity(
playerInfo.oldPositionInfo,
@ -2466,22 +2452,22 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
if (!Util.areEqual(oldPlayerInfo.mediaMetadata, playerInfo.mediaMetadata)) {
listeners.queueEvent(
Player.EVENT_MEDIA_METADATA_CHANGED,
/* eventFlag= */ Player.EVENT_MEDIA_METADATA_CHANGED,
listener -> listener.onMediaMetadataChanged(playerInfo.mediaMetadata));
}
if (oldPlayerInfo.seekBackIncrementMs != playerInfo.seekBackIncrementMs) {
listeners.queueEvent(
Player.EVENT_SEEK_BACK_INCREMENT_CHANGED,
/* eventFlag= */ Player.EVENT_SEEK_BACK_INCREMENT_CHANGED,
listener -> listener.onSeekBackIncrementChanged(playerInfo.seekBackIncrementMs));
}
if (oldPlayerInfo.seekForwardIncrementMs != playerInfo.seekForwardIncrementMs) {
listeners.queueEvent(
Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
/* eventFlag= */ Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
listener -> listener.onSeekForwardIncrementChanged(playerInfo.seekForwardIncrementMs));
}
if (oldPlayerInfo.maxSeekToPreviousPositionMs != newPlayerInfo.maxSeekToPreviousPositionMs) {
listeners.queueEvent(
Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED,
/* eventFlag= */ Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED,
listener ->
listener.onMaxSeekToPreviousPositionChanged(
newPlayerInfo.maxSeekToPreviousPositionMs));
@ -2489,7 +2475,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
if (!Util.areEqual(
oldPlayerInfo.trackSelectionParameters, newPlayerInfo.trackSelectionParameters)) {
listeners.queueEvent(
Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
/* eventFlag= */ Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED,
listener ->
listener.onTrackSelectionParametersChanged(newPlayerInfo.trackSelectionParameters));
}
@ -2519,7 +2505,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
if (intersectedPlayerCommandsChanged) {
listeners.sendEvent(
Player.EVENT_AVAILABLE_COMMANDS_CHANGED,
/* eventFlag= */ Player.EVENT_AVAILABLE_COMMANDS_CHANGED,
listener -> listener.onAvailableCommandsChanged(intersectedPlayerCommands));
}
if (sessionCommandsChanged) {
@ -2544,7 +2530,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
!Util.areEqual(intersectedPlayerCommands, prevIntersectedPlayerCommands);
if (intersectedPlayerCommandsChanged) {
listeners.sendEvent(
Player.EVENT_AVAILABLE_COMMANDS_CHANGED,
/* eventFlag= */ Player.EVENT_AVAILABLE_COMMANDS_CHANGED,
listener -> listener.onAvailableCommandsChanged(intersectedPlayerCommands));
}
}
@ -2583,7 +2569,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
public void onRenderedFirstFrame() {
listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onRenderedFirstFrame);
listeners.sendEvent(
/* eventFlag= */ Player.EVENT_RENDERED_FIRST_FRAME, Listener::onRenderedFirstFrame);
}
private void updateSessionPositionInfoIfNeeded(SessionPositionInfo sessionPositionInfo) {

View File

@ -51,6 +51,7 @@ interface IRemoteMediaSession {
void setIsPlayingAd(String sessionId, boolean isPlayingAd);
void setCurrentAdGroupIndex(String sessionId, int currentAdGroupIndex);
void setCurrentAdIndexInAdGroup(String sessionId, int currentAdIndexInAdGroup);
void setVolume(String sessionId, float volume);
void notifyPlayerError(String sessionId, in Bundle playerErrorBundle);
void notifyPlayWhenReadyChanged(String sessionId, boolean playWhenReady, int reason);
void notifyPlaybackStateChanged(String sessionId, int state);
@ -79,6 +80,8 @@ interface IRemoteMediaSession {
void notifySeekBackIncrementChanged(String sessionId, long seekBackIncrementMs);
void notifySeekForwardIncrementChanged(String sessionId, long seekForwardIncrementMs);
void notifyDeviceVolumeChanged(String sessionId, int volume, boolean muted);
void decreaseDeviceVolume(String sessionId);
void increaseDeviceVolume(String sessionId);
void notifyCuesChanged(String sessionId, in Bundle cueGroup);
void notifyDeviceInfoChanged(String sessionId, in Bundle deviceInfo);
void notifyMediaMetadataChanged(String sessionId, in Bundle mediaMetadata);

View File

@ -24,8 +24,10 @@ import android.text.TextUtils;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.Locale;
/** Provides utility methods for testing purpose. */
@ -127,5 +129,19 @@ public class TestUtils {
}
}
/**
* Returns an {@link ImmutableList} with the {@linkplain Player.Event Events} contained in {@code
* events}. The contents of the list are in matching order with the {@linkplain Player.Event
* Events} returned by {@link Player.Events#get(int)}.
*/
// TODO(b/254265256): Move this method off test-session-common.
public static ImmutableList<@Player.Event Integer> getEventsAsList(Player.Events events) {
ImmutableList.Builder<@Player.Event Integer> list = new ImmutableList.Builder<>();
for (int i = 0; i < events.size(); i++) {
list.add(events.get(i));
}
return list.build();
}
private TestUtils() {}
}

View File

@ -15,16 +15,12 @@
*/
package androidx.media3.session;
import static androidx.media3.common.DeviceInfo.PLAYBACK_TYPE_LOCAL;
import static androidx.media3.common.Player.REPEAT_MODE_ALL;
import static androidx.media3.common.Player.REPEAT_MODE_ONE;
import static androidx.media3.common.Player.STATE_ENDED;
import static androidx.media3.common.Player.STATE_READY;
import static androidx.media3.session.MediaTestUtils.createMediaItems;
import static androidx.media3.session.MediaTestUtils.createTimeline;
import static androidx.media3.test.session.common.CommonConstants.DEFAULT_TEST_NAME;
import static androidx.media3.test.session.common.TestUtils.NO_RESPONSE_TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.getEventsAsList;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@ -43,8 +39,10 @@ import androidx.media3.common.Player.PositionInfo;
import androidx.media3.common.Timeline;
import androidx.media3.common.Timeline.Period;
import androidx.media3.common.Timeline.Window;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.test.session.common.HandlerThreadTestRule;
import androidx.media3.test.session.common.MainLooperTestRule;
import androidx.media3.test.session.common.TestUtils;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
@ -161,10 +159,11 @@ public class MediaControllerStateMaskingTest {
assertThat(playWhenReadyFromCallbackRef.get()).isEqualTo(testPlayWhenReady);
assertThat(playbackSuppressionReasonFromCallbackRef.get()).isEqualTo(testReason);
assertThat(isPlayingFromCallbackRef.get()).isEqualTo(testIsPlaying);
assertThat(onEventsRef.get().contains(Player.EVENT_PLAY_WHEN_READY_CHANGED)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED))
.isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_IS_PLAYING_CHANGED)).isTrue();
assertThat(TestUtils.getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_PLAY_WHEN_READY_CHANGED,
Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
Player.EVENT_IS_PLAYING_CHANGED);
assertThat(playWhenReadyFromGetterRef.get()).isEqualTo(testPlayWhenReady);
assertThat(playbackSuppressionReasonFromGetterRef.get()).isEqualTo(testReason);
assertThat(isPlayingFromGetterRef.get()).isEqualTo(testIsPlaying);
@ -208,15 +207,18 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(shuffleModeEnabledFromCallbackRef.get()).isEqualTo(testShuffleModeEnabled);
assertThat(onEventsRef.get().contains(Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED);
assertThat(shuffleModeEnabledFromGetterRef.get()).isEqualTo(testShuffleModeEnabled);
}
@Test
public void setRepeatMode() throws Exception {
int testRepeatMode = REPEAT_MODE_ALL;
int testRepeatMode = Player.REPEAT_MODE_ALL;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder().setRepeatMode(REPEAT_MODE_ONE).build();
new RemoteMediaSession.MockPlayerConfigBuilder()
.setRepeatMode(Player.REPEAT_MODE_ONE)
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
@ -250,7 +252,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(repeatModeFromCallbackRef.get()).isEqualTo(testRepeatMode);
assertThat(onEventsRef.get().contains(Player.EVENT_REPEAT_MODE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_REPEAT_MODE_CHANGED);
assertThat(repeatModeFromGetterRef.get()).isEqualTo(testRepeatMode);
}
@ -294,7 +297,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackParametersFromCallbackRef.get()).isEqualTo(testPlaybackParameters);
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_PARAMETERS_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_PLAYBACK_PARAMETERS_CHANGED);
assertThat(playbackParametersFromGetterRef.get()).isEqualTo(testPlaybackParameters);
}
@ -338,7 +342,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackParametersFromCallbackRef.get().speed).isEqualTo(testPlaybackSpeed);
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_PARAMETERS_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_PLAYBACK_PARAMETERS_CHANGED);
assertThat(playbackParametersFromGetterRef.get().speed).isEqualTo(testPlaybackSpeed);
}
@ -354,6 +359,7 @@ public class MediaControllerStateMaskingTest {
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicReference<MediaMetadata> playlistMetadataFromCallbackRef = new AtomicReference<>();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -364,6 +370,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -381,6 +388,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playlistMetadataFromCallbackRef.get()).isEqualTo(testPlaylistMetadata);
assertThat(playlistMetadataFromGetterRef.get()).isEqualTo(testPlaylistMetadata);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_PLAYLIST_METADATA_CHANGED);
}
@Test
@ -392,6 +401,7 @@ public class MediaControllerStateMaskingTest {
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicReference<Float> volumeFromCallbackRef = new AtomicReference<>();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -402,6 +412,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -419,6 +430,7 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(volumeFromCallbackRef.get()).isEqualTo(testVolume);
assertThat(volumeFromGetterRef.get()).isEqualTo(testVolume);
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_VOLUME_CHANGED);
}
@Test
@ -431,6 +443,7 @@ public class MediaControllerStateMaskingTest {
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicInteger deviceVolumeFromCallbackRef = new AtomicInteger();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -441,6 +454,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -458,6 +472,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromCallbackRef.get()).isEqualTo(testDeviceVolume);
assertThat(deviceVolumeFromGetterRef.get()).isEqualTo(testDeviceVolume);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_DEVICE_VOLUME_CHANGED);
}
@Test
@ -467,13 +483,15 @@ public class MediaControllerStateMaskingTest {
new RemoteMediaSession.MockPlayerConfigBuilder()
.setDeviceVolume(1)
.setDeviceInfo(
new DeviceInfo(PLAYBACK_TYPE_LOCAL, /* minVolume= */ 0, /* maxVolume= */ 2))
new DeviceInfo(
DeviceInfo.PLAYBACK_TYPE_LOCAL, /* minVolume= */ 0, /* maxVolume= */ 2))
.build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicInteger deviceVolumeFromCallbackRef = new AtomicInteger();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -484,6 +502,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -501,6 +520,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromCallbackRef.get()).isEqualTo(testDeviceVolume);
assertThat(deviceVolumeFromGetterRef.get()).isEqualTo(testDeviceVolume);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_DEVICE_VOLUME_CHANGED);
}
@Test
@ -513,6 +534,7 @@ public class MediaControllerStateMaskingTest {
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicInteger deviceVolumeFromCallbackRef = new AtomicInteger();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -523,6 +545,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -540,6 +563,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromCallbackRef.get()).isEqualTo(testDeviceVolume);
assertThat(deviceVolumeFromGetterRef.get()).isEqualTo(testDeviceVolume);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_DEVICE_VOLUME_CHANGED);
}
@Test
@ -552,6 +577,7 @@ public class MediaControllerStateMaskingTest {
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicBoolean deviceMutedFromCallbackRef = new AtomicBoolean();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -562,6 +588,7 @@ public class MediaControllerStateMaskingTest {
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
@ -579,6 +606,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceMutedFromCallbackRef.get()).isEqualTo(testDeviceMuted);
assertThat(deviceMutedFromGetterRef.get()).isEqualTo(testDeviceMuted);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_DEVICE_VOLUME_CHANGED);
}
@Test
@ -628,11 +657,57 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateFromCallbackRef.get()).isEqualTo(testPlaybackState);
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_STATE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_PLAYBACK_STATE_CHANGED);
assertThat(playbackStateFromGetterRef.get()).isEqualTo(testPlaybackState);
assertThat(playerErrorRef.get()).isNull();
}
@Test
public void setTrackSelectionParameters() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
remoteSession.setPlayer(new RemoteMediaSession.MockPlayerConfigBuilder().build());
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(2);
AtomicReference<TrackSelectionParameters> trackSelectionParametersCallbackRef =
new AtomicReference<>();
AtomicReference<TrackSelectionParameters> trackSelectionParametersGetterRef =
new AtomicReference<>();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) {
trackSelectionParametersCallbackRef.set(parameters);
latch.countDown();
}
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
threadTestRule
.getHandler()
.postAndSync(
() -> {
controller.setTrackSelectionParameters(
new TrackSelectionParameters.Builder(context).setMaxVideoBitrate(1234).build());
trackSelectionParametersGetterRef.set(controller.getTrackSelectionParameters());
});
TrackSelectionParameters expectedParameters =
new TrackSelectionParameters.Builder(context).setMaxVideoBitrate(1234).build();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(trackSelectionParametersCallbackRef.get()).isEqualTo(expectedParameters);
assertThat(trackSelectionParametersGetterRef.get()).isEqualTo(expectedParameters);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED);
}
@Test
public void seekToNextMediaItem() throws Exception {
int initialMediaItemIndex = 1;
@ -694,8 +769,8 @@ public class MediaControllerStateMaskingTest {
assertThat(newMediaItemRef.get().mediaId).isEqualTo(testCurrentMediaId);
assertThat(oldPositionInfoRef.get().mediaItemIndex).isEqualTo(initialMediaItemIndex);
assertThat(newPositionInfoRef.get().mediaItemIndex).isEqualTo(testMediaItemIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_MEDIA_ITEM_TRANSITION, Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
}
@ -760,8 +835,8 @@ public class MediaControllerStateMaskingTest {
assertThat(newMediaItemRef.get().mediaId).isEqualTo(testCurrentMediaId);
assertThat(oldPositionInfoRef.get().mediaItemIndex).isEqualTo(initialMediaItemIndex);
assertThat(newPositionInfoRef.get().mediaItemIndex).isEqualTo(testMediaItemIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_MEDIA_ITEM_TRANSITION, Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
}
@ -827,7 +902,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
assertThat(bufferedPositionRef.get()).isEqualTo(testBufferedPosition);
assertThat(totalBufferedDurationRef.get()).isEqualTo(testTotalBufferedDuration);
@ -896,7 +972,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
assertThat(bufferedPositionRef.get()).isEqualTo(testBufferedPosition);
assertThat(totalBufferedDurationRef.get()).isEqualTo(testTotalBufferedDuration);
@ -965,7 +1042,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
assertThat(bufferedPositionRef.get()).isEqualTo(testBufferedPosition);
assertThat(totalBufferedDurationRef.get()).isEqualTo(testTotalBufferedDuration);
@ -1035,7 +1113,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
assertThat(bufferedPositionRef.get()).isEqualTo(testBufferedPosition);
@ -1145,7 +1224,7 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).contains(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
@ -1282,7 +1361,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testSeekPositionMs);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
@ -1326,9 +1406,10 @@ public class MediaControllerStateMaskingTest {
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(2);
AtomicLong oldPositionRef = new AtomicLong();
AtomicLong newPositionRef = new AtomicLong();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -1338,6 +1419,12 @@ public class MediaControllerStateMaskingTest {
newPositionRef.set(newPosition.positionMs);
latch.countDown();
}
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
controller.addListener(listener);
@ -1346,6 +1433,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(oldPositionRef.get()).isEqualTo(testCurrentPosition);
assertThat(newPositionRef.get()).isEqualTo(testCurrentPosition - testSeekBackIncrement);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
}
@Test
@ -1361,9 +1450,10 @@ public class MediaControllerStateMaskingTest {
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(2);
AtomicLong oldPositionRef = new AtomicLong();
AtomicLong newPositionRef = new AtomicLong();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -1373,6 +1463,12 @@ public class MediaControllerStateMaskingTest {
newPositionRef.set(newPosition.positionMs);
latch.countDown();
}
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
controller.addListener(listener);
@ -1381,6 +1477,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(oldPositionRef.get()).isEqualTo(testCurrentPosition);
assertThat(newPositionRef.get()).isEqualTo(testCurrentPosition + testSeekForwardIncrement);
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_POSITION_DISCONTINUITY);
}
@Test
@ -1462,7 +1560,11 @@ public class MediaControllerStateMaskingTest {
testMediaItemIndex,
/* testFirstPeriodIndex= */ testPeriodIndex,
/* testLastPeriodIndex= */ testPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_TIMELINE_CHANGED,
Player.EVENT_MEDIA_ITEM_TRANSITION,
Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
@ -1561,9 +1663,11 @@ public class MediaControllerStateMaskingTest {
/* testFirstPeriodIndex= */ testPeriodIndex,
/* testLastPeriodIndex= */ testPeriodIndex);
assertThat(newMediaItemRef.get().mediaId).isEqualTo(testMediaItemIndexMediaId);
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_POSITION_DISCONTINUITY,
Player.EVENT_TIMELINE_CHANGED,
Player.EVENT_MEDIA_ITEM_TRANSITION);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
@ -1655,9 +1759,11 @@ public class MediaControllerStateMaskingTest {
assertThat(newPositionInfoRef.get().positionMs).isEqualTo(testPosition);
assertThat(newTimelineRef.get().isEmpty()).isTrue();
assertThat(newMediaItemRef.get()).isNull();
assertThat(onEventsRef.get().contains(Player.EVENT_POSITION_DISCONTINUITY)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_POSITION_DISCONTINUITY,
Player.EVENT_TIMELINE_CHANGED,
Player.EVENT_MEDIA_ITEM_TRANSITION);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testPeriodIndex);
assertThat(currentPositionRef.get()).isEqualTo(testPosition);
@ -1751,7 +1857,8 @@ public class MediaControllerStateMaskingTest {
testCurrentMediaItemIndex,
/* testFirstPeriodIndex= */ testCurrentPeriodIndex,
/* testLastPeriodIndex= */ testCurrentPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_TIMELINE_CHANGED, Player.EVENT_MEDIA_ITEM_TRANSITION);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -1819,7 +1926,7 @@ public class MediaControllerStateMaskingTest {
testCurrentMediaItemIndex,
/* testFirstPeriodIndex= */ testCurrentPeriodIndex,
/* testLastPeriodIndex= */ testCurrentPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -1937,7 +2044,7 @@ public class MediaControllerStateMaskingTest {
testCurrentMediaItemIndex,
/* testFirstPeriodIndex= */ testCurrentWindowFirstPeriodIndex,
/* testLastPeriodIndex= */ testCurrentWindowLastPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -2026,8 +2133,11 @@ public class MediaControllerStateMaskingTest {
/* testLastPeriodIndex= */ testCurrentMediaItemIndex);
assertThat(newMediaItemRef.get().mediaId).isEqualTo(testCurrentMediaId);
assertThat(newPositionInfoRef.get().mediaItemIndex).isEqualTo(testCurrentMediaItemIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_TIMELINE_CHANGED,
Player.EVENT_MEDIA_ITEM_TRANSITION,
Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -2101,7 +2211,7 @@ public class MediaControllerStateMaskingTest {
Window window = new Window();
assertThat(newTimelineRef.get().getWindow(testCurrentMediaItemIndex, window).mediaItem.mediaId)
.isEqualTo(testCurrentMediaId);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -2171,7 +2281,7 @@ public class MediaControllerStateMaskingTest {
testCurrentMediaItemIndex,
/* testFirstPeriodIndex= */ testCurrentWindowFirstPeriodIndex,
/* testLastPeriodIndex= */ testCurrentWindowLastPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testCurrentPeriodIndex);
}
@ -2179,7 +2289,7 @@ public class MediaControllerStateMaskingTest {
@Test
public void removeMediaItems_removeAllItems() throws Exception {
int initialMediaItemIndex = 1;
int initialPlaybackState = STATE_READY;
int initialPlaybackState = Player.STATE_READY;
long initialCurrentPosition = 3_000;
String firstMediaId = "firstMediaId";
String secondMediaId = "secondMediaId";
@ -2190,7 +2300,7 @@ public class MediaControllerStateMaskingTest {
int testCurrentMediaItemIndex = 0;
int testNextMediaItemIndex = C.INDEX_UNSET;
int testPreviousMediaItemIndex = C.INDEX_UNSET;
int testPlaybackState = STATE_ENDED;
int testPlaybackState = Player.STATE_ENDED;
long testCurrentPosition = 0;
Bundle playerConfig =
@ -2264,9 +2374,12 @@ public class MediaControllerStateMaskingTest {
/* ignored= */ C.INDEX_UNSET);
assertThat(newMediaItemRef.get()).isNull();
assertThat(newPlaybackStateRef.get()).isEqualTo(testPlaybackState);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_MEDIA_ITEM_TRANSITION)).isTrue();
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_STATE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(
Player.EVENT_TIMELINE_CHANGED,
Player.EVENT_MEDIA_ITEM_TRANSITION,
Player.EVENT_PLAYBACK_STATE_CHANGED,
Player.EVENT_POSITION_DISCONTINUITY);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(nextMediaItemIndexRef.get()).isEqualTo(testNextMediaItemIndex);
assertThat(previousMediaItemIndexRef.get()).isEqualTo(testPreviousMediaItemIndex);
@ -2277,10 +2390,10 @@ public class MediaControllerStateMaskingTest {
public void removeMediaItems_removedTailIncludesCurrentItem_callsOnPlaybackStateChanged()
throws Exception {
int initialMediaItemIndex = 1;
int initialPlaybackState = STATE_READY;
int initialPlaybackState = Player.STATE_READY;
int testFromIndex = 1;
int testToIndex = 3;
int testPlaybackState = STATE_ENDED;
int testPlaybackState = Player.STATE_ENDED;
Timeline testTimeline = createTimeline(createMediaItems(/* size= */ 3));
Bundle playerConfig =
@ -2293,8 +2406,9 @@ public class MediaControllerStateMaskingTest {
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
CountDownLatch latch = new CountDownLatch(1);
CountDownLatch latch = new CountDownLatch(2);
AtomicInteger newPlaybackStateRef = new AtomicInteger();
AtomicReference<Player.Events> onEventsRef = new AtomicReference<>();
Player.Listener listener =
new Player.Listener() {
@Override
@ -2302,6 +2416,12 @@ public class MediaControllerStateMaskingTest {
newPlaybackStateRef.set(playbackState);
latch.countDown();
}
@Override
public void onEvents(Player player, Player.Events events) {
onEventsRef.set(events);
latch.countDown();
}
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
@ -2314,6 +2434,7 @@ public class MediaControllerStateMaskingTest {
});
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newPlaybackStateRef.get()).isEqualTo(testPlaybackState);
assertThat(getEventsAsList(onEventsRef.get())).contains(Player.EVENT_PLAYBACK_STATE_CHANGED);
}
@Test
@ -2586,7 +2707,7 @@ public class MediaControllerStateMaskingTest {
assertThat(
newTimelineRef.get().getWindow(testNextMediaItemIndex, new Window()).mediaItem.mediaId)
.isEqualTo(testNextMediaId);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
}
@ -2700,7 +2821,7 @@ public class MediaControllerStateMaskingTest {
testCurrentMediaItemIndex,
/* testFirstPeriodIndex= */ testCurrentWindowFirstPeriodIndex,
/* testLastPeriodIndex= */ testCurrentWindowLastPeriodIndex);
assertThat(onEventsRef.get().contains(Player.EVENT_TIMELINE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get())).containsExactly(Player.EVENT_TIMELINE_CHANGED);
assertThat(currentMediaItemIndexRef.get()).isEqualTo(testCurrentMediaItemIndex);
assertThat(currentPeriodIndexRef.get()).isEqualTo(testCurrentPeriodIndex);
}
@ -2867,7 +2988,8 @@ public class MediaControllerStateMaskingTest {
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateFromCallbackRef.get()).isEqualTo(testPlaybackState);
assertThat(onEventsRef.get().contains(Player.EVENT_PLAYBACK_STATE_CHANGED)).isTrue();
assertThat(getEventsAsList(onEventsRef.get()))
.containsExactly(Player.EVENT_PLAYBACK_STATE_CHANGED);
assertThat(playbackStateFromGetterRef.get()).isEqualTo(testPlaybackState);
assertThat(playerErrorFromGetterRef.get().errorInfoEquals(testPlaybackException)).isTrue();
assertThat(timelineFromGetterRef.get().getWindowCount())

View File

@ -35,6 +35,7 @@ import androidx.media3.common.Player;
import androidx.media3.test.session.common.HandlerThreadTestRule;
import androidx.media3.test.session.common.PollingCheck;
import androidx.media3.test.session.common.SurfaceActivity;
import androidx.media3.test.session.common.TestUtils;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
@ -42,6 +43,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@ -140,6 +142,7 @@ public class MediaControllerSurfaceSizeChangeTest {
private final CountDownLatch countDownLatch;
private final AtomicInteger newSurfaceWidthRef;
private final AtomicInteger newSurfaceHeightRef;
private final AtomicReference<Player.Events> eventsRef;
@Rule
public ActivityTestRule<SurfaceActivity> activityRule =
@ -178,9 +181,10 @@ public class MediaControllerSurfaceSizeChangeTest {
this.sizeCondition = sizeCondition;
this.surfaceSizeChangedShouldBeCalled = surfaceSizeChangedShouldBeCalled;
countDownLatch = new CountDownLatch(1);
countDownLatch = new CountDownLatch(2);
newSurfaceWidthRef = new AtomicInteger(C.LENGTH_UNSET);
newSurfaceHeightRef = new AtomicInteger(C.LENGTH_UNSET);
eventsRef = new AtomicReference<>();
}
@Test
@ -252,6 +256,12 @@ public class MediaControllerSurfaceSizeChangeTest {
newSurfaceHeightRef.set(height);
countDownLatch.countDown();
}
@Override
public void onEvents(Player player, Player.Events events) {
eventsRef.set(events);
countDownLatch.countDown();
}
}));
}
@ -360,6 +370,8 @@ public class MediaControllerSurfaceSizeChangeTest {
assertThat(countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(newSurfaceWidthRef.get()).isEqualTo(expectedWidthFromCallback);
assertThat(newSurfaceHeightRef.get()).isEqualTo(expectedHeightFromCallback);
assertThat(TestUtils.getEventsAsList(eventsRef.get()))
.containsExactly(Player.EVENT_SURFACE_SIZE_CHANGED);
} else {
assertThat(countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
}

View File

@ -857,6 +857,17 @@ public class MediaSessionProviderService extends Service {
});
}
@Override
public void setVolume(String sessionId, float volume) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.setVolume(volume);
player.notifyVolumeChanged();
});
}
@Override
public void notifyAvailableCommandsChanged(String sessionId, Bundle commandsBundle)
throws RemoteException {
@ -970,6 +981,28 @@ public class MediaSessionProviderService extends Service {
});
}
@Override
public void decreaseDeviceVolume(String sessionId) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.decreaseDeviceVolume();
player.notifyDeviceVolumeChanged();
});
}
@Override
public void increaseDeviceVolume(String sessionId) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.increaseDeviceVolume();
player.notifyDeviceVolumeChanged();
});
}
@Override
public void notifyCuesChanged(String sessionId, Bundle cueGroupBundle) throws RemoteException {
CueGroup cueGroup = CueGroup.CREATOR.fromBundle(cueGroupBundle);

View File

@ -655,11 +655,13 @@ public class MockPlayer implements Player {
@Override
public void increaseDeviceVolume() {
deviceVolume += 1;
checkNotNull(conditionVariables.get(METHOD_INCREASE_DEVICE_VOLUME)).open();
}
@Override
public void decreaseDeviceVolume() {
deviceVolume -= 1;
checkNotNull(conditionVariables.get(METHOD_DECREASE_DEVICE_VOLUME)).open();
}
@ -1204,6 +1206,12 @@ public class MockPlayer implements Player {
}
}
public void notifyVolumeChanged() {
for (Listener listener : listeners) {
listener.onVolumeChanged(volume);
}
}
@SuppressWarnings("deprecation") // Implementing and calling deprecated listener method.
public void notifyCuesChanged() {
for (Listener listener : listeners) {

View File

@ -282,6 +282,10 @@ public class RemoteMediaSession {
binder.setCurrentAdIndexInAdGroup(sessionId, currentAdIndexInAdGroup);
}
public void setVolume(float volume) throws RemoteException {
binder.setVolume(sessionId, volume);
}
public void notifyPlayWhenReadyChanged(
boolean playWhenReady, @Player.PlaybackSuppressionReason int reason)
throws RemoteException {
@ -399,6 +403,14 @@ public class RemoteMediaSession {
binder.notifyDeviceVolumeChanged(sessionId, volume, muted);
}
public void decreaseDeviceVolume() throws RemoteException {
binder.decreaseDeviceVolume(sessionId);
}
public void increaseDeviceVolume() throws RemoteException {
binder.increaseDeviceVolume(sessionId);
}
public void notifyCuesChanged(CueGroup cueGroup) throws RemoteException {
binder.notifyCuesChanged(sessionId, cueGroup.toBundle());
}