diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index a3a140c772..7b474770a3 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -1677,7 +1677,8 @@ public class MediaController implements Player { @Override public Tracks getCurrentTracks() { - return Tracks.EMPTY; // TODO(b/178486745) + verifyApplicationThread(); + return isConnected() ? impl.getCurrentTracks() : Tracks.EMPTY; } @Override @@ -2010,6 +2011,8 @@ public class MediaController implements Player { Commands getAvailableCommands(); + Tracks getCurrentTracks(); + TrackSelectionParameters getTrackSelectionParameters(); void setTrackSelectionParameters(TrackSelectionParameters parameters); diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java index d9d804c1e6..4434e2f2b4 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplBase.java @@ -57,6 +57,7 @@ import static androidx.media3.common.Player.EVENT_SEEK_BACK_INCREMENT_CHANGED; import static androidx.media3.common.Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED; import static androidx.media3.common.Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED; import static androidx.media3.common.Player.EVENT_TIMELINE_CHANGED; +import static androidx.media3.common.Player.EVENT_TRACKS_CHANGED; import static androidx.media3.common.Player.EVENT_TRACK_SELECTION_PARAMETERS_CHANGED; import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED; import static androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT; @@ -132,6 +133,7 @@ import androidx.media3.common.Timeline.Period; import androidx.media3.common.Timeline.RemotableTimeline; import androidx.media3.common.Timeline.Window; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.BundleableUtil; @@ -1766,6 +1768,11 @@ import org.checkerframework.checker.nullness.qual.NonNull; return intersectedPlayerCommands; } + @Override + public Tracks getCurrentTracks() { + return playerInfo.currentTracks; + } + @Override public TrackSelectionParameters getTrackSelectionParameters() { return playerInfo.trackSelectionParameters; @@ -2388,6 +2395,10 @@ import org.checkerframework.checker.nullness.qual.NonNull; listener.onMediaItemTransition( currentMediaItem, playerInfo.mediaItemTransitionReason)); } + if (!Util.areEqual(oldPlayerInfo.currentTracks, newPlayerInfo.currentTracks)) { + listeners.queueEvent( + EVENT_TRACKS_CHANGED, listener -> listener.onTracksChanged(newPlayerInfo.currentTracks)); + } if (!Util.areEqual(oldPlayerInfo.playbackParameters, playerInfo.playbackParameters)) { listeners.queueEvent( EVENT_PLAYBACK_PARAMETERS_CHANGED, diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index 04006c7e53..893c6ecd92 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -83,6 +83,7 @@ import androidx.media3.common.Rating; import androidx.media3.common.Timeline; import androidx.media3.common.Timeline.Window; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Clock; @@ -1184,6 +1185,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; return controllerInfo.availablePlayerCommands; } + @Override + public Tracks getCurrentTracks() { + return Tracks.EMPTY; + } + @Override public TrackSelectionParameters getTrackSelectionParameters() { return TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT; @@ -2102,6 +2108,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; seekBackIncrementMs, seekForwardIncrementMs, /* maxSeekToPreviousPositionMs= */ 0L, + /* currentTracks= */ Tracks.EMPTY, /* parameters= */ TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT); return new ControllerInfo( diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index d170298328..12e188ef09 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -51,6 +51,7 @@ import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Rating; import androidx.media3.common.Timeline; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; @@ -1123,6 +1124,8 @@ public class MediaSession { default void onIsLoadingChanged(int seq, boolean isLoading) throws RemoteException {} + default void onTracksChanged(int seq, Tracks tracks) throws RemoteException {} + default void onTrackSelectionParametersChanged(int seq, TrackSelectionParameters parameters) throws RemoteException {} diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index 6f720629fe..c1924412e6 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -61,6 +61,7 @@ import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Rating; import androidx.media3.common.Timeline; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Log; @@ -401,13 +402,13 @@ import org.checkerframework.checker.initialization.qual.Initialized; .onPlayerInfoChanged( seq, playerInfo, - !sessionStub + /* excludeMediaItems= */ !sessionStub .getConnectedControllersManager() .isPlayerCommandAvailable(controller, Player.COMMAND_GET_TIMELINE), - !sessionStub + /* excludeMediaItemsMetadata= */ !sessionStub .getConnectedControllersManager() .isPlayerCommandAvailable(controller, Player.COMMAND_GET_MEDIA_ITEMS_METADATA), - !sessionStub + /* excludeCues= */ !sessionStub .getConnectedControllersManager() .isPlayerCommandAvailable(controller, Player.COMMAND_GET_TEXT), excludeTimeline); @@ -1087,6 +1088,23 @@ import org.checkerframework.checker.initialization.qual.Initialized; (callback, seq) -> callback.onDeviceInfoChanged(seq, session.playerInfo.deviceInfo)); } + @Override + public void onTracksChanged(Tracks tracks) { + @Nullable MediaSessionImpl session = getSession(); + if (session == null) { + return; + } + session.verifyApplicationThread(); + @Nullable PlayerWrapper player = this.player.get(); + if (player == null) { + return; + } + session.playerInfo = session.playerInfo.copyWithCurrentTracks(tracks); + session.onPlayerInfoChangedHandler.sendPlayerInfoChangedMessage(/* excludeTimeline= */ true); + session.dispatchRemoteControllerTaskWithoutReturn( + (callback, seq) -> callback.onTracksChanged(seq, tracks)); + } + @Override public void onTrackSelectionParametersChanged(TrackSelectionParameters parameters) { @Nullable MediaSessionImpl session = getSession(); diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java index 6b886bb568..6be5b3e5b7 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java @@ -42,6 +42,7 @@ import androidx.media3.common.Player.State; import androidx.media3.common.Timeline; import androidx.media3.common.Timeline.Window; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Assertions; @@ -90,6 +91,7 @@ import java.lang.annotation.Target; private long seekBackIncrementMs; private long seekForwardIncrementMs; private long maxSeekToPreviousPositionMs; + private Tracks currentTracks; private TrackSelectionParameters trackSelectionParameters; public Builder(PlayerInfo playerInfo) { @@ -121,6 +123,7 @@ import java.lang.annotation.Target; seekBackIncrementMs = playerInfo.seekBackIncrementMs; seekForwardIncrementMs = playerInfo.seekForwardIncrementMs; maxSeekToPreviousPositionMs = playerInfo.maxSeekToPreviousPositionMs; + currentTracks = playerInfo.currentTracks; trackSelectionParameters = playerInfo.trackSelectionParameters; } @@ -267,6 +270,11 @@ import java.lang.annotation.Target; return this; } + public Builder setCurrentTracks(Tracks tracks) { + currentTracks = tracks; + return this; + } + public Builder setTrackSelectionParameters(TrackSelectionParameters parameters) { trackSelectionParameters = parameters; return this; @@ -305,6 +313,7 @@ import java.lang.annotation.Target; seekBackIncrementMs, seekForwardIncrementMs, maxSeekToPreviousPositionMs, + currentTracks, trackSelectionParameters); } } @@ -350,6 +359,7 @@ import java.lang.annotation.Target; /* seekBackIncrementMs= */ 0, /* seekForwardIncrementMs= */ 0, /* maxSeekToPreviousPositionMs= */ 0, + /* currentTracks= */ Tracks.EMPTY, TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT); @Nullable public final PlaybackException playerError; @@ -408,6 +418,8 @@ import java.lang.annotation.Target; public final long maxSeekToPreviousPositionMs; + public final Tracks currentTracks; + public final TrackSelectionParameters trackSelectionParameters; @CheckResult @@ -578,6 +590,10 @@ import java.lang.annotation.Target; return new Builder(this).setMaxSeekToPreviousPositionMs(maxSeekToPreviousPositionMs).build(); } + public PlayerInfo copyWithCurrentTracks(Tracks tracks) { + return new Builder(this).setCurrentTracks(tracks).build(); + } + @CheckResult public PlayerInfo copyWithTrackSelectionParameters(TrackSelectionParameters parameters) { return new Builder(this).setTrackSelectionParameters(parameters).build(); @@ -612,6 +628,7 @@ import java.lang.annotation.Target; long seekBackIncrementMs, long seekForwardIncrementMs, long maxSeekToPreviousPositionMs, + Tracks currentTracks, TrackSelectionParameters parameters) { this.playerError = playerError; this.mediaItemTransitionReason = mediaItemTransitionReason; @@ -641,6 +658,7 @@ import java.lang.annotation.Target; this.seekBackIncrementMs = seekBackIncrementMs; this.seekForwardIncrementMs = seekForwardIncrementMs; this.maxSeekToPreviousPositionMs = maxSeekToPreviousPositionMs; + this.currentTracks = currentTracks; this.trackSelectionParameters = parameters; } @@ -696,6 +714,7 @@ import java.lang.annotation.Target; FIELD_SEEK_FORWARD_INCREMENT_MS, FIELD_MAX_SEEK_TO_PREVIOUS_POSITION_MS, FIELD_TRACK_SELECTION_PARAMETERS, + FIELD_CURRENT_TRACKS, }) private @interface FieldNumber {} @@ -728,7 +747,8 @@ import java.lang.annotation.Target; private static final int FIELD_SEEK_FORWARD_INCREMENT_MS = 27; private static final int FIELD_MAX_SEEK_TO_PREVIOUS_POSITION_MS = 28; private static final int FIELD_TRACK_SELECTION_PARAMETERS = 29; - // Next field key = 30 + private static final int FIELD_CURRENT_TRACKS = 30; + // Next field key = 31 public Bundle toBundle( boolean excludeMediaItems, @@ -774,6 +794,7 @@ import java.lang.annotation.Target; bundle.putLong(keyForField(FIELD_SEEK_FORWARD_INCREMENT_MS), seekForwardIncrementMs); bundle.putLong( keyForField(FIELD_MAX_SEEK_TO_PREVIOUS_POSITION_MS), maxSeekToPreviousPositionMs); + bundle.putBundle(keyForField(FIELD_CURRENT_TRACKS), currentTracks.toBundle()); bundle.putBundle( keyForField(FIELD_TRACK_SELECTION_PARAMETERS), trackSelectionParameters.toBundle()); @@ -886,6 +907,9 @@ import java.lang.annotation.Target; bundle.getLong(keyForField(FIELD_SEEK_FORWARD_INCREMENT_MS), /* defaultValue= */ 0); long maxSeekToPreviousPosition = bundle.getLong(keyForField(FIELD_MAX_SEEK_TO_PREVIOUS_POSITION_MS), /* defaultValue= */ 0); + Bundle currentTracksBundle = bundle.getBundle(keyForField(FIELD_CURRENT_TRACKS)); + Tracks currentTracks = + currentTracksBundle == null ? Tracks.EMPTY : Tracks.CREATOR.fromBundle(currentTracksBundle); @Nullable Bundle trackSelectionParametersBundle = bundle.getBundle(keyForField(FIELD_TRACK_SELECTION_PARAMETERS)); @@ -922,6 +946,7 @@ import java.lang.annotation.Target; seekBackIncrementMs, seekForwardIncrementMs, maxSeekToPreviousPosition, + currentTracks, trackSelectionParameters); } diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java index d1f25b41cd..793fdd1136 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java @@ -951,6 +951,7 @@ import java.util.List; getSeekBackIncrement(), getSeekForwardIncrement(), getMaxSeekToPreviousPosition(), + getCurrentTracks(), getTrackSelectionParameters()); } diff --git a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl index 4711fa62b1..008bcc2545 100644 --- a/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl +++ b/libraries/test_session_common/src/main/aidl/androidx/media3/test/session/common/IRemoteMediaSession.aidl @@ -85,4 +85,5 @@ interface IRemoteMediaSession { void notifyRenderedFirstFrame(String sessionId); void notifyMaxSeekToPreviousPositionChanged(String sessionid, long maxSeekToPreviousPositionMs); void notifyTrackSelectionParametersChanged(String sessionId, in Bundle parameters); + void notifyTracksChanged(String sessionId, in Bundle tracks); } diff --git a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java index 3260732471..64a92bd2a8 100644 --- a/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java +++ b/libraries/test_session_common/src/main/java/androidx/media3/test/session/common/CommonConstants.java @@ -103,6 +103,7 @@ public class CommonConstants { public static final String KEY_MEDIA_METADATA = "mediaMetadata"; public static final String KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS = "maxSeekToPreviousPositionMs"; public static final String KEY_TRACK_SELECTION_PARAMETERS = "trackSelectionParameters"; + public static final String KEY_CURRENT_TRACKS = "currentTracks"; // SessionCompat arguments public static final String KEY_SESSION_COMPAT_TOKEN = "sessionCompatToken"; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java index b84b90a9a6..904f4a8bc4 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerTest.java @@ -50,6 +50,7 @@ import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; import androidx.media3.common.DeviceInfo; import androidx.media3.common.FlagSet; +import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.media3.common.MediaMetadata; import androidx.media3.common.PlaybackException; @@ -62,7 +63,9 @@ import androidx.media3.common.Player.PositionInfo; import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Player.State; import androidx.media3.common.Timeline; +import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.Cue; import androidx.media3.common.text.CueGroup; @@ -829,6 +832,52 @@ public class MediaControllerListenerTest { assertThat(parametersFromGetterRef.get()).isEqualTo(parameters); } + @Test + public void onTracksChanged() throws Exception { + RemoteMediaSession.RemoteMockPlayer player = remoteSession.getMockPlayer(); + ImmutableList trackGroups = + ImmutableList.of( + new Tracks.Group( + new TrackGroup(new Format.Builder().setChannelCount(2).build()), + /* adaptiveSupported= */ false, + /* trackSupport= */ new int[1], + /* trackSelected= */ new boolean[1]), + new Tracks.Group( + new TrackGroup(new Format.Builder().setHeight(1024).build()), + /* adaptiveSupported= */ false, + /* trackSupport= */ new int[1], + /* trackSelected= */ new boolean[1])); + Tracks currentTracks = new Tracks(trackGroups); + MediaController controller = controllerTestRule.createController(remoteSession.getToken()); + AtomicReference changedCurrentTracksFromParamRef = new AtomicReference<>(); + AtomicReference changedCurrentTracksFromGetterRef = new AtomicReference<>(); + CountDownLatch latch = new CountDownLatch(1); + Player.Listener listener = + new Player.Listener() { + @Override + public void onTracksChanged(Tracks currentTracks) { + changedCurrentTracksFromParamRef.set(currentTracks); + changedCurrentTracksFromGetterRef.set(controller.getCurrentTracks()); + latch.countDown(); + } + }; + AtomicReference initialCurrentTracksRef = new AtomicReference<>(); + threadTestRule + .getHandler() + .postAndSync( + () -> { + initialCurrentTracksRef.set(controller.getCurrentTracks()); + controller.addListener(listener); + }); + + player.notifyTracksChanged(currentTracks); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(initialCurrentTracksRef.get()).isEqualTo(Tracks.EMPTY); + assertThat(changedCurrentTracksFromParamRef.get()).isEqualTo(currentTracks); + assertThat(changedCurrentTracksFromGetterRef.get()).isEqualTo(currentTracks); + } + /** This also tests {@link MediaController#getShuffleModeEnabled()}. */ @Test public void onShuffleModeEnabledChanged() throws Exception { diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java index 63ea9ad1c9..07cbfff83e 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerTest.java @@ -35,6 +35,7 @@ import android.os.Bundle; import android.os.RemoteException; import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; +import androidx.media3.common.Format; import androidx.media3.common.HeartRating; import androidx.media3.common.IllegalSeekPositionException; import androidx.media3.common.MediaItem; @@ -47,7 +48,9 @@ import androidx.media3.common.Player.RepeatMode; import androidx.media3.common.Rating; import androidx.media3.common.StarRating; import androidx.media3.common.Timeline; +import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.util.Util; import androidx.media3.test.session.common.HandlerThreadTestRule; @@ -283,6 +286,22 @@ public class MediaControllerTest { long seekBackIncrementMs = 1_000; long seekForwardIncrementMs = 2_000; long maxSeekToPreviousPositionMs = 300; + ImmutableList trackGroups = + new ImmutableList.Builder() + .add( + new Tracks.Group( + new TrackGroup(new Format.Builder().setChannelCount(2).build()), + /* adaptiveSupported= */ false, + /* trackSupport= */ new int[1], + /* trackSelected= */ new boolean[1])) + .add( + new Tracks.Group( + new TrackGroup(new Format.Builder().setHeight(1024).build()), + /* adaptiveSupported= */ false, + /* trackSupport= */ new int[1], + /* trackSelected= */ new boolean[1])) + .build(); + Tracks currentTracks = new Tracks(trackGroups); TrackSelectionParameters trackSelectionParameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT.buildUpon().setMaxVideoSizeSd().build(); Timeline timeline = MediaTestUtils.createTimeline(5); @@ -316,6 +335,7 @@ public class MediaControllerTest { .setSeekForwardIncrement(seekForwardIncrementMs) .setMaxSeekToPreviousPositionMs(maxSeekToPreviousPositionMs) .setTrackSelectionParameters(trackSelectionParameters) + .setCurrentTracks(currentTracks) .setTimeline(timeline) .setCurrentMediaItemIndex(currentMediaItemIndex) .build(); @@ -347,6 +367,7 @@ public class MediaControllerTest { AtomicLong seekBackIncrementRef = new AtomicLong(); AtomicLong seekForwardIncrementRef = new AtomicLong(); AtomicLong maxSeekToPreviousPositionMsRef = new AtomicLong(); + AtomicReference currentTracksRef = new AtomicReference<>(); AtomicReference trackSelectionParametersRef = new AtomicReference<>(); AtomicReference timelineRef = new AtomicReference<>(); AtomicInteger currentMediaItemIndexRef = new AtomicInteger(); @@ -379,6 +400,7 @@ public class MediaControllerTest { seekBackIncrementRef.set(controller.getSeekBackIncrement()); seekForwardIncrementRef.set(controller.getSeekForwardIncrement()); maxSeekToPreviousPositionMsRef.set(controller.getMaxSeekToPreviousPosition()); + currentTracksRef.set(controller.getCurrentTracks()); trackSelectionParametersRef.set(controller.getTrackSelectionParameters()); timelineRef.set(controller.getCurrentTimeline()); currentMediaItemIndexRef.set(controller.getCurrentMediaItemIndex()); @@ -409,6 +431,7 @@ public class MediaControllerTest { assertThat(seekForwardIncrementRef.get()).isEqualTo(seekForwardIncrementMs); assertThat(maxSeekToPreviousPositionMsRef.get()).isEqualTo(maxSeekToPreviousPositionMs); assertThat(trackSelectionParametersRef.get()).isEqualTo(trackSelectionParameters); + assertThat(currentTracksRef.get()).isEqualTo(currentTracks); assertTimelineMediaItemsEquals(timelineRef.get(), timeline); assertThat(currentMediaItemIndexRef.get()).isEqualTo(currentMediaItemIndex); assertThat(currentMediaItemRef.get()).isEqualTo(currentMediaItem); diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java index fa4605cfaa..9336008501 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaSessionProviderService.java @@ -29,6 +29,7 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_LI import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_MEDIA_ITEM_INDEX; import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_PERIOD_INDEX; import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_POSITION; +import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_TRACKS; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_INFO; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_MUTED; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME; @@ -79,6 +80,7 @@ import androidx.media3.common.Player.DiscontinuityReason; import androidx.media3.common.Player.PositionInfo; import androidx.media3.common.Timeline; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Log; @@ -355,6 +357,10 @@ public class MediaSessionProviderService extends Service { } player.maxSeekToPreviousPositionMs = config.getLong(KEY_MAX_SEEK_TO_PREVIOUS_POSITION_MS, player.maxSeekToPreviousPositionMs); + @Nullable Bundle currentTracksBundle = config.getBundle(KEY_CURRENT_TRACKS); + if (currentTracksBundle != null) { + player.currentTracks = Tracks.CREATOR.fromBundle(currentTracksBundle); + } @Nullable Bundle trackSelectionParametersBundle = config.getBundle(KEY_TRACK_SELECTION_PARAMETERS); if (trackSelectionParametersBundle != null) { @@ -1004,5 +1010,17 @@ public class MediaSessionProviderService extends Service { player.notifyTrackSelectionParametersChanged(); }); } + + @Override + public void notifyTracksChanged(String sessionId, Bundle tracksBundle) throws RemoteException { + Tracks tracks = Tracks.CREATOR.fromBundle(tracksBundle); + runOnHandler( + () -> { + MediaSession session = sessionMap.get(sessionId); + MockPlayer player = (MockPlayer) session.getPlayer(); + player.currentTracks = tracks; + player.notifyTracksChanged(); + }); + } } } diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java index ee26b18e33..e08b20c595 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MockPlayer.java @@ -251,6 +251,7 @@ public class MockPlayer implements Player { public long seekForwardIncrementMs; public long maxSeekToPreviousPositionMs; public TrackSelectionParameters trackSelectionParameters; + public Tracks currentTracks; private MockPlayer(Builder builder) { changePlayerStateWithTransportControl = builder.changePlayerStateWithTransportControl; @@ -299,6 +300,7 @@ public class MockPlayer implements Player { commands = new Player.Commands.Builder().addAllCommands().build(); + currentTracks = Tracks.EMPTY; trackSelectionParameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT; } @@ -1177,6 +1179,22 @@ public class MockPlayer implements Player { } } + @Override + public Tracks getCurrentTracks() { + return currentTracks; + } + + @Override + public TrackSelectionParameters getTrackSelectionParameters() { + return trackSelectionParameters; + } + + @Override + public void setTrackSelectionParameters(TrackSelectionParameters parameters) { + trackSelectionParameters = parameters; + checkNotNull(conditionVariables.get(METHOD_SET_TRACK_SELECTION_PARAMETERS)).open(); + } + public boolean surfaceExists() { return surface != null; } @@ -1225,20 +1243,10 @@ public class MockPlayer implements Player { } } - @Override - public Tracks getCurrentTracks() { - throw new UnsupportedOperationException(); - } - - @Override - public TrackSelectionParameters getTrackSelectionParameters() { - return trackSelectionParameters; - } - - @Override - public void setTrackSelectionParameters(TrackSelectionParameters parameters) { - trackSelectionParameters = parameters; - checkNotNull(conditionVariables.get(METHOD_SET_TRACK_SELECTION_PARAMETERS)).open(); + public void notifyTracksChanged() { + for (Listener listener : listeners) { + listener.onTracksChanged(currentTracks); + } } @Override diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java index 9d22d6df39..45da31105f 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/RemoteMediaSession.java @@ -29,6 +29,7 @@ import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_LI import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_MEDIA_ITEM_INDEX; import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_PERIOD_INDEX; import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_POSITION; +import static androidx.media3.test.session.common.CommonConstants.KEY_CURRENT_TRACKS; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_INFO; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_MUTED; import static androidx.media3.test.session.common.CommonConstants.KEY_DEVICE_VOLUME; @@ -77,6 +78,7 @@ import androidx.media3.common.Player.DiscontinuityReason; import androidx.media3.common.Player.PositionInfo; import androidx.media3.common.Timeline; import androidx.media3.common.TrackSelectionParameters; +import androidx.media3.common.Tracks; import androidx.media3.common.VideoSize; import androidx.media3.common.text.CueGroup; import androidx.media3.common.util.Log; @@ -421,6 +423,10 @@ public class RemoteMediaSession { throws RemoteException { binder.notifyTrackSelectionParametersChanged(sessionId, parameters.toBundle()); } + + public void notifyTracksChanged(Tracks tracks) throws RemoteException { + binder.notifyTracksChanged(sessionId, tracks.toBundle()); + } } //////////////////////////////////////////////////////////////////////////////// @@ -687,6 +693,11 @@ public class RemoteMediaSession { return this; } + public MockPlayerConfigBuilder setCurrentTracks(Tracks tracks) { + bundle.putBundle(KEY_CURRENT_TRACKS, tracks.toBundle()); + return this; + } + public Bundle build() { return bundle; }