diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 740af1cf88..19658d2c12 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,6 +47,8 @@ Release notes for custom players. * Add helper method to convert platform session token to Media3 `SessionToken` ([#171](https://github.com/androidx/media/issues/171)). + * Use `onMediaMetadataChanged` to trigger updates of the platform media + session ([#219](https://github.com/androidx/media/issues/219)). * Metadata: * Parse multiple null-separated values from ID3 frames, as permitted by ID3 v2.4. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java index 2215b07071..069534ffad 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -91,6 +91,7 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -850,12 +851,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; private final class ControllerLegacyCbForBroadcast implements ControllerCb { - @Nullable private MediaItem currentMediaItemForMetadataUpdate; - - private long durationMsForMetadataUpdate; + private MediaMetadata lastMediaMetadata; + private String lastMediaId; + @Nullable private Uri lastMediaUri; + private long lastDurationMs; public ControllerLegacyCbForBroadcast() { - durationMsForMetadataUpdate = C.TIME_UNSET; + lastMediaMetadata = MediaMetadata.EMPTY; + lastMediaId = MediaItem.DEFAULT_MEDIA_ID; + lastDurationMs = C.TIME_UNSET; } @Override @@ -992,6 +996,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; public void onMediaItemTransition( int seq, @Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) throws RemoteException { + // MediaMetadataCompat needs to be updated when the media ID or URI of the media item changes. updateMetadataIfChanged(); if (mediaItem == null) { sessionCompat.setRatingType(RatingCompat.RATING_NONE); @@ -1004,6 +1009,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); } + @Override + public void onMediaMetadataChanged(int seq, MediaMetadata mediaMetadata) { + updateMetadataIfChanged(); + } + @Override public void onTimelineChanged( int seq, Timeline timeline, @Player.TimelineChangeReason int reason) @@ -1014,7 +1024,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } updateQueue(timeline); - // Duration might be unknown at onMediaItemTransition and become available afterward. updateMetadataIfChanged(); } @@ -1146,22 +1155,30 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); } - @Override - public void onMediaMetadataChanged(int seq, MediaMetadata mediaMetadata) { - // Metadata change will be notified by onMediaItemTransition. - } - private void updateMetadataIfChanged() { - @Nullable MediaItem currentMediaItem = sessionImpl.getPlayerWrapper().getCurrentMediaItem(); - long durationMs = sessionImpl.getPlayerWrapper().getDuration(); + Player player = sessionImpl.getPlayerWrapper(); + @Nullable MediaItem currentMediaItem = player.getCurrentMediaItem(); + MediaMetadata newMediaMetadata = player.getMediaMetadata(); + long newDurationMs = player.getDuration(); + String newMediaId = + currentMediaItem != null ? currentMediaItem.mediaId : MediaItem.DEFAULT_MEDIA_ID; + @Nullable + Uri newMediaUri = + currentMediaItem != null && currentMediaItem.localConfiguration != null + ? currentMediaItem.localConfiguration.uri + : null; - if (ObjectsCompat.equals(currentMediaItemForMetadataUpdate, currentMediaItem) - && durationMsForMetadataUpdate == durationMs) { + if (Objects.equals(lastMediaMetadata, newMediaMetadata) + && Objects.equals(lastMediaId, newMediaId) + && Objects.equals(lastMediaUri, newMediaUri) + && lastDurationMs == newDurationMs) { return; } - currentMediaItemForMetadataUpdate = currentMediaItem; - durationMsForMetadataUpdate = durationMs; + lastMediaId = newMediaId; + lastMediaUri = newMediaUri; + lastMediaMetadata = newMediaMetadata; + lastDurationMs = newDurationMs; if (currentMediaItem == null) { setMetadata(sessionCompat, /* metadataCompat= */ null); @@ -1170,7 +1187,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; @Nullable Bitmap artworkBitmap = null; ListenableFuture bitmapFuture = - sessionImpl.getBitmapLoader().loadBitmapFromMetadata(currentMediaItem.mediaMetadata); + sessionImpl.getBitmapLoader().loadBitmapFromMetadata(newMediaMetadata); if (bitmapFuture != null) { pendingBitmapLoadCallback = null; if (bitmapFuture.isDone()) { @@ -1190,7 +1207,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; setMetadata( sessionCompat, MediaUtils.convertToMediaMetadataCompat( - currentMediaItem, durationMs, result)); + newMediaMetadata, + newMediaId, + newMediaUri, + newDurationMs, + /* artworkBitmap= */ result)); sessionImpl.onNotificationRefreshRequired(); } @@ -1210,7 +1231,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } setMetadata( sessionCompat, - MediaUtils.convertToMediaMetadataCompat(currentMediaItem, durationMs, artworkBitmap)); + MediaUtils.convertToMediaMetadataCompat( + newMediaMetadata, newMediaId, newMediaUri, newDurationMs, artworkBitmap)); } } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java index 11735dd6ac..716f08a29d 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java @@ -531,14 +531,25 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; return null; } - /** Converts a {@link MediaItem} to a {@link MediaMetadataCompat}. */ + /** + * Converts a {@link MediaMetadata} to a {@link MediaMetadataCompat}. + * + * @param metadata The {@link MediaMetadata} instance to convert. + * @param mediaId The corresponding media ID. + * @param mediaUri The corresponding media URI, or null if unknown. + * @param durationMs The duration of the media, in milliseconds or {@link C#TIME_UNSET}, if no + * duration should be included. + * @return An instance of the legacy {@link MediaMetadataCompat}. + */ public static MediaMetadataCompat convertToMediaMetadataCompat( - MediaItem mediaItem, long durationMs, @Nullable Bitmap artworkBitmap) { + MediaMetadata metadata, + String mediaId, + @Nullable Uri mediaUri, + long durationMs, + @Nullable Bitmap artworkBitmap) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder() - .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaItem.mediaId); - - MediaMetadata metadata = mediaItem.mediaMetadata; + .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId); if (metadata.title != null) { builder.putText(MediaMetadataCompat.METADATA_KEY_TITLE, metadata.title); @@ -569,10 +580,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, metadata.recordingYear); } - if (mediaItem.requestMetadata.mediaUri != null) { - builder.putString( - MediaMetadataCompat.METADATA_KEY_MEDIA_URI, - mediaItem.requestMetadata.mediaUri.toString()); + if (mediaUri != null) { + builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_URI, mediaUri.toString()); } if (metadata.artworkUri != null) { @@ -597,21 +606,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, durationMs); } - @Nullable - RatingCompat userRatingCompat = convertToRatingCompat(mediaItem.mediaMetadata.userRating); + @Nullable RatingCompat userRatingCompat = convertToRatingCompat(metadata.userRating); if (userRatingCompat != null) { builder.putRating(MediaMetadataCompat.METADATA_KEY_USER_RATING, userRatingCompat); } - @Nullable - RatingCompat overallRatingCompat = convertToRatingCompat(mediaItem.mediaMetadata.overallRating); + @Nullable RatingCompat overallRatingCompat = convertToRatingCompat(metadata.overallRating); if (overallRatingCompat != null) { builder.putRating(MediaMetadataCompat.METADATA_KEY_RATING, overallRatingCompat); } - if (mediaItem.mediaMetadata.mediaType != null) { - builder.putLong( - MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT, mediaItem.mediaMetadata.mediaType); + if (metadata.mediaType != null) { + builder.putLong(MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT, metadata.mediaType); } return builder.build(); 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 5220083112..c7b50fa114 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 @@ -67,6 +67,7 @@ interface IRemoteMediaSession { void setTimeline(String sessionId, in Bundle timeline); void createAndSetFakeTimeline(String sessionId, int windowCount); + void setMediaMetadata(String sessionId, in Bundle metadata); void setPlaylistMetadata(String sessionId, in Bundle metadata); void setShuffleModeEnabled(String sessionId, boolean shuffleMode); void setRepeatMode(String sessionId, int repeatMode); diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java index 77d06b7244..71543ae0fe 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerCompatCallbackWithMediaSessionTest.java @@ -127,6 +127,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { .setBufferedPosition(testBufferingPosition) .setPlaybackParameters(new PlaybackParameters(testSpeed)) .setTimeline(testTimeline) + .setMediaMetadata(testMediaItems.get(testItemIndex).mediaMetadata) .setPlaylistMetadata(testPlaylistMetadata) .setCurrentMediaItemIndex(testItemIndex) .setShuffleModeEnabled(testShuffleModeEnabled) @@ -370,6 +371,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { .setDuration(testDurationMs) .setPlaybackParameters(playbackParameters) .setTimeline(testTimeline) + .setMediaMetadata(testMediaItems.get(testItemIndex).mediaMetadata) .setPlaylistMetadata(testPlaylistMetadata) .setCurrentMediaItemIndex(testItemIndex) .setShuffleModeEnabled(testShuffleModeEnabled) @@ -979,53 +981,68 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { } @Test - public void currentMediaItemChange() throws Exception { + public void onMediaItemTransition_updatesLegacyMetadataAndPlaybackState_correctModelConversion() + throws Exception { int testItemIndex = 3; long testPosition = 1234; String testDisplayTitle = "displayTitle"; + long testDurationMs = 30_000; List testMediaItems = MediaTestUtils.createMediaItems(/* size= */ 5); + String testCurrentMediaId = testMediaItems.get(testItemIndex).mediaId; + MediaMetadata testMediaMetadata = + new MediaMetadata.Builder().setTitle(testDisplayTitle).build(); testMediaItems.set( testItemIndex, new MediaItem.Builder() .setMediaId(testMediaItems.get(testItemIndex).mediaId) - .setMediaMetadata(new MediaMetadata.Builder().setTitle(testDisplayTitle).build()) + .setMediaMetadata(testMediaMetadata) .build()); - Timeline timeline = new PlaylistTimeline(testMediaItems); - session.getMockPlayer().setTimeline(timeline); + session.getMockPlayer().setTimeline(new PlaylistTimeline(testMediaItems)); + session.getMockPlayer().setCurrentMediaItemIndex(testItemIndex); + session.getMockPlayer().setCurrentPosition(testPosition); + session.getMockPlayer().setDuration(testDurationMs); + session.getMockPlayer().setMediaMetadata(testMediaMetadata); AtomicReference metadataRef = new AtomicReference<>(); AtomicReference playbackStateRef = new AtomicReference<>(); CountDownLatch latchForMetadata = new CountDownLatch(1); CountDownLatch latchForPlaybackState = new CountDownLatch(1); + List callbackOrder = new ArrayList<>(); MediaControllerCompat.Callback callback = new MediaControllerCompat.Callback() { @Override public void onMetadataChanged(MediaMetadataCompat metadata) { metadataRef.set(metadata); + callbackOrder.add("onMetadataChanged"); latchForMetadata.countDown(); } @Override public void onPlaybackStateChanged(PlaybackStateCompat state) { playbackStateRef.set(state); + callbackOrder.add("onPlaybackStateChanged"); latchForPlaybackState.countDown(); } }; controllerCompat.registerCallback(callback, handler); - session.getMockPlayer().setCurrentMediaItemIndex(testItemIndex); - session.getMockPlayer().setCurrentPosition(testPosition); session .getMockPlayer() .notifyMediaItemTransition(testItemIndex, Player.MEDIA_ITEM_TRANSITION_REASON_SEEK); + // Assert metadata. assertThat(latchForMetadata.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); - assertThat(metadataRef.get().getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + MediaMetadataCompat parameterMetadataCompat = metadataRef.get(); + MediaMetadataCompat getterMetadataCompat = controllerCompat.getMetadata(); + assertThat(parameterMetadataCompat.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) .isEqualTo(testDisplayTitle); - assertThat( - controllerCompat - .getMetadata() - .getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + assertThat(getterMetadataCompat.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) .isEqualTo(testDisplayTitle); + assertThat(parameterMetadataCompat.getLong(METADATA_KEY_DURATION)).isEqualTo(testDurationMs); + assertThat(getterMetadataCompat.getLong(METADATA_KEY_DURATION)).isEqualTo(testDurationMs); + assertThat(parameterMetadataCompat.getString(METADATA_KEY_MEDIA_ID)) + .isEqualTo(testCurrentMediaId); + assertThat(getterMetadataCompat.getString(METADATA_KEY_MEDIA_ID)).isEqualTo(testCurrentMediaId); + // Assert the playback state. assertThat(latchForPlaybackState.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(playbackStateRef.get().getPosition()).isEqualTo(testPosition); assertThat(controllerCompat.getPlaybackState().getPosition()).isEqualTo(testPosition); @@ -1033,6 +1050,56 @@ public class MediaControllerCompatCallbackWithMediaSessionTest { .isEqualTo(MediaUtils.convertToQueueItemId(testItemIndex)); assertThat(controllerCompat.getPlaybackState().getActiveQueueItemId()) .isEqualTo(MediaUtils.convertToQueueItemId(testItemIndex)); + assertThat(callbackOrder) + .containsExactly("onMetadataChanged", "onPlaybackStateChanged") + .inOrder(); + } + + @Test + public void onMediaMetadataChanged_updatesLegacyMetadata_correctModelConversion() + throws Exception { + int testItemIndex = 3; + String testDisplayTitle = "displayTitle"; + long testDurationMs = 30_000; + List testMediaItems = MediaTestUtils.createMediaItems(/* size= */ 5); + String testCurrentMediaId = testMediaItems.get(testItemIndex).mediaId; + MediaMetadata testMediaMetadata = + new MediaMetadata.Builder().setTitle(testDisplayTitle).build(); + testMediaItems.set( + testItemIndex, + new MediaItem.Builder() + .setMediaId(testMediaItems.get(testItemIndex).mediaId) + .setMediaMetadata(testMediaMetadata) + .build()); + session.getMockPlayer().setTimeline(new PlaylistTimeline(testMediaItems)); + session.getMockPlayer().setCurrentMediaItemIndex(testItemIndex); + session.getMockPlayer().setDuration(testDurationMs); + AtomicReference metadataRef = new AtomicReference<>(); + CountDownLatch latchForMetadata = new CountDownLatch(1); + MediaControllerCompat.Callback callback = + new MediaControllerCompat.Callback() { + @Override + public void onMetadataChanged(MediaMetadataCompat metadata) { + metadataRef.set(metadata); + latchForMetadata.countDown(); + } + }; + controllerCompat.registerCallback(callback, handler); + + session.getMockPlayer().notifyMediaMetadataChanged(testMediaMetadata); + + assertThat(latchForMetadata.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + MediaMetadataCompat parameterMetadataCompat = metadataRef.get(); + MediaMetadataCompat getterMetadataCompat = controllerCompat.getMetadata(); + assertThat(parameterMetadataCompat.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + .isEqualTo(testDisplayTitle); + assertThat(getterMetadataCompat.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + .isEqualTo(testDisplayTitle); + assertThat(parameterMetadataCompat.getLong(METADATA_KEY_DURATION)).isEqualTo(testDurationMs); + assertThat(getterMetadataCompat.getLong(METADATA_KEY_DURATION)).isEqualTo(testDurationMs); + assertThat(parameterMetadataCompat.getString(METADATA_KEY_MEDIA_ID)) + .isEqualTo(testCurrentMediaId); + assertThat(getterMetadataCompat.getString(METADATA_KEY_MEDIA_ID)).isEqualTo(testCurrentMediaId); } @Test diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java index b735477ce7..e07afb4422 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithMediaSessionCompatTest.java @@ -714,7 +714,11 @@ public class MediaControllerWithMediaSessionCompatTest { MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); + testRemoveMediaItem.mediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + /* artworkBitmap= */ null); session.setQueue(testQueue); session.setMetadata(testMetadataCompat); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -732,7 +736,11 @@ public class MediaControllerWithMediaSessionCompatTest { MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); + testRemoveMediaItem.mediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + /* artworkBitmap= */ null); session.setQueue(testQueue); session.setMetadata(testMetadataCompat); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -767,7 +775,11 @@ public class MediaControllerWithMediaSessionCompatTest { MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); + testRemoveMediaItem.mediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + /* artworkBitmap= */ null); session.setQueue(testQueue); session.setMetadata(testMetadataCompat); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -785,7 +797,11 @@ public class MediaControllerWithMediaSessionCompatTest { MediaMetadata testMediaMetadata = testMediaItem.mediaMetadata; MediaMetadataCompat testMediaMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); + testMediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + /* artworkBitmap= */ null); session.setMetadata(testMediaMetadataCompat); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -803,7 +819,11 @@ public class MediaControllerWithMediaSessionCompatTest { @Nullable Bitmap artworkBitmap = getBitmapFromMetadata(testMediaMetadata); MediaMetadataCompat testMediaMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testMediaItem, /* durationMs= */ 100L, artworkBitmap); + testMediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + artworkBitmap); session.setMetadata(testMediaMetadataCompat); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -1141,9 +1161,14 @@ public class MediaControllerWithMediaSessionCompatTest { @Test public void setPlaybackState_fromStateBufferingToPlaying_notifiesReadyState() throws Exception { List testPlaylist = MediaTestUtils.createMediaItems(/* size= */ 1); + MediaItem firstMediaItemInPlaylist = testPlaylist.get(0); MediaMetadataCompat metadata = MediaUtils.convertToMediaMetadataCompat( - testPlaylist.get(0), /* durationMs= */ 50_000, /* artworkBitmap= */ null); + firstMediaItemInPlaylist.mediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 50_000, + /* artworkBitmap= */ null); long testBufferedPosition = 5_000; session.setMetadata(metadata); session.setPlaybackState( @@ -1186,9 +1211,14 @@ public class MediaControllerWithMediaSessionCompatTest { public void setPlaybackState_fromStatePlayingToBuffering_notifiesBufferingState() throws Exception { List testPlaylist = MediaTestUtils.createMediaItems(1); + MediaItem firstMediaItemInPlaylist = testPlaylist.get(0); MediaMetadataCompat metadata = MediaUtils.convertToMediaMetadataCompat( - testPlaylist.get(0), /* durationMs= */ 1_000, /* artworkBitmap= */ null); + firstMediaItemInPlaylist.mediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 1_000, + /* artworkBitmap= */ null); long testBufferingPosition = 0; session.setMetadata(metadata); session.setPlaybackState( diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java index 59209c334a..9511124a5b 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaUtilsTest.java @@ -29,6 +29,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import android.content.Context; import android.graphics.Bitmap; +import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.service.media.MediaBrowserService; @@ -217,7 +218,11 @@ public final class MediaUtilsTest { } MediaMetadataCompat testMediaMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - testMediaItem, /* durationMs= */ 100L, testArtworkBitmap); + testMediaMetadata, + "mediaId", + Uri.parse("http://example.com"), + /* durationMs= */ 100L, + testArtworkBitmap); MediaMetadata mediaMetadata = MediaUtils.convertToMediaMetadata(testMediaMetadataCompat, RatingCompat.RATING_NONE); @@ -258,7 +263,11 @@ public final class MediaUtilsTest { MediaMetadataCompat mediaMetadataCompat = MediaUtils.convertToMediaMetadataCompat( - mediaItem, /* durotionsMs= */ C.TIME_UNSET, /* artworkBitmap= */ null); + mediaItem.mediaMetadata, + "mediaId", + Uri.parse("http://www.example.com"), + /* durotionsMs= */ C.TIME_UNSET, + /* artworkBitmap= */ null); assertThat( mediaMetadataCompat.getLong( 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 ce0c68eb09..d48253eed7 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 @@ -801,6 +801,16 @@ public class MediaSessionProviderService extends Service { }); } + @Override + public void setMediaMetadata(String sessionId, Bundle metadataBundle) throws RemoteException { + runOnHandler( + () -> { + MediaSession session = sessionMap.get(sessionId); + MockPlayer player = (MockPlayer) session.getPlayer(); + player.mediaMetadata = MediaMetadata.CREATOR.fromBundle(metadataBundle); + }); + } + @Override public void setPlaylistMetadata(String sessionId, Bundle playlistMetadataBundle) throws RemoteException { 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 7d5cadfa8d..ca2840480d 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 @@ -360,6 +360,10 @@ public class RemoteMediaSession { binder.setTrackSelectionParameters(sessionId, parameters.toBundle()); } + public void setMediaMetadata(MediaMetadata mediaMetadata) throws RemoteException { + binder.setMediaMetadata(sessionId, mediaMetadata.toBundle()); + } + public void notifyTimelineChanged(@Player.TimelineChangeReason int reason) throws RemoteException { binder.notifyTimelineChanged(sessionId, reason);