Use onMediaMetadataChanged for updating the legacy session

Issue: androidx/media#219
PiperOrigin-RevId: 501080612
This commit is contained in:
bachinger 2023-01-10 21:31:35 +00:00 committed by Rohit Singh
parent 9882a20783
commit 375299bf36
9 changed files with 206 additions and 55 deletions

View File

@ -47,6 +47,8 @@ Release notes
for custom players. for custom players.
* Add helper method to convert platform session token to Media3 * Add helper method to convert platform session token to Media3
`SessionToken` ([#171](https://github.com/androidx/media/issues/171)). `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: * Metadata:
* Parse multiple null-separated values from ID3 frames, as permitted by * Parse multiple null-separated values from ID3 frames, as permitted by
ID3 v2.4. ID3 v2.4.

View File

@ -91,6 +91,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -850,12 +851,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private final class ControllerLegacyCbForBroadcast implements ControllerCb { private final class ControllerLegacyCbForBroadcast implements ControllerCb {
@Nullable private MediaItem currentMediaItemForMetadataUpdate; private MediaMetadata lastMediaMetadata;
private String lastMediaId;
private long durationMsForMetadataUpdate; @Nullable private Uri lastMediaUri;
private long lastDurationMs;
public ControllerLegacyCbForBroadcast() { public ControllerLegacyCbForBroadcast() {
durationMsForMetadataUpdate = C.TIME_UNSET; lastMediaMetadata = MediaMetadata.EMPTY;
lastMediaId = MediaItem.DEFAULT_MEDIA_ID;
lastDurationMs = C.TIME_UNSET;
} }
@Override @Override
@ -992,6 +996,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
public void onMediaItemTransition( public void onMediaItemTransition(
int seq, @Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) int seq, @Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason)
throws RemoteException { throws RemoteException {
// MediaMetadataCompat needs to be updated when the media ID or URI of the media item changes.
updateMetadataIfChanged(); updateMetadataIfChanged();
if (mediaItem == null) { if (mediaItem == null) {
sessionCompat.setRatingType(RatingCompat.RATING_NONE); sessionCompat.setRatingType(RatingCompat.RATING_NONE);
@ -1004,6 +1009,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
.setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat());
} }
@Override
public void onMediaMetadataChanged(int seq, MediaMetadata mediaMetadata) {
updateMetadataIfChanged();
}
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(
int seq, Timeline timeline, @Player.TimelineChangeReason int reason) int seq, Timeline timeline, @Player.TimelineChangeReason int reason)
@ -1014,7 +1024,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} }
updateQueue(timeline); updateQueue(timeline);
// Duration might be unknown at onMediaItemTransition and become available afterward. // Duration might be unknown at onMediaItemTransition and become available afterward.
updateMetadataIfChanged(); updateMetadataIfChanged();
} }
@ -1146,22 +1155,30 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
.setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat()); .setPlaybackState(sessionImpl.getPlayerWrapper().createPlaybackStateCompat());
} }
@Override
public void onMediaMetadataChanged(int seq, MediaMetadata mediaMetadata) {
// Metadata change will be notified by onMediaItemTransition.
}
private void updateMetadataIfChanged() { private void updateMetadataIfChanged() {
@Nullable MediaItem currentMediaItem = sessionImpl.getPlayerWrapper().getCurrentMediaItem(); Player player = sessionImpl.getPlayerWrapper();
long durationMs = sessionImpl.getPlayerWrapper().getDuration(); @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) if (Objects.equals(lastMediaMetadata, newMediaMetadata)
&& durationMsForMetadataUpdate == durationMs) { && Objects.equals(lastMediaId, newMediaId)
&& Objects.equals(lastMediaUri, newMediaUri)
&& lastDurationMs == newDurationMs) {
return; return;
} }
currentMediaItemForMetadataUpdate = currentMediaItem; lastMediaId = newMediaId;
durationMsForMetadataUpdate = durationMs; lastMediaUri = newMediaUri;
lastMediaMetadata = newMediaMetadata;
lastDurationMs = newDurationMs;
if (currentMediaItem == null) { if (currentMediaItem == null) {
setMetadata(sessionCompat, /* metadataCompat= */ null); setMetadata(sessionCompat, /* metadataCompat= */ null);
@ -1170,7 +1187,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable Bitmap artworkBitmap = null; @Nullable Bitmap artworkBitmap = null;
ListenableFuture<Bitmap> bitmapFuture = ListenableFuture<Bitmap> bitmapFuture =
sessionImpl.getBitmapLoader().loadBitmapFromMetadata(currentMediaItem.mediaMetadata); sessionImpl.getBitmapLoader().loadBitmapFromMetadata(newMediaMetadata);
if (bitmapFuture != null) { if (bitmapFuture != null) {
pendingBitmapLoadCallback = null; pendingBitmapLoadCallback = null;
if (bitmapFuture.isDone()) { if (bitmapFuture.isDone()) {
@ -1190,7 +1207,11 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
setMetadata( setMetadata(
sessionCompat, sessionCompat,
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
currentMediaItem, durationMs, result)); newMediaMetadata,
newMediaId,
newMediaUri,
newDurationMs,
/* artworkBitmap= */ result));
sessionImpl.onNotificationRefreshRequired(); sessionImpl.onNotificationRefreshRequired();
} }
@ -1210,7 +1231,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
} }
setMetadata( setMetadata(
sessionCompat, sessionCompat,
MediaUtils.convertToMediaMetadataCompat(currentMediaItem, durationMs, artworkBitmap)); MediaUtils.convertToMediaMetadataCompat(
newMediaMetadata, newMediaId, newMediaUri, newDurationMs, artworkBitmap));
} }
} }

View File

@ -531,14 +531,25 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return null; 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( 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 = MediaMetadataCompat.Builder builder =
new MediaMetadataCompat.Builder() new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaItem.mediaId); .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId);
MediaMetadata metadata = mediaItem.mediaMetadata;
if (metadata.title != null) { if (metadata.title != null) {
builder.putText(MediaMetadataCompat.METADATA_KEY_TITLE, metadata.title); 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); builder.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, metadata.recordingYear);
} }
if (mediaItem.requestMetadata.mediaUri != null) { if (mediaUri != null) {
builder.putString( builder.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_URI, mediaUri.toString());
MediaMetadataCompat.METADATA_KEY_MEDIA_URI,
mediaItem.requestMetadata.mediaUri.toString());
} }
if (metadata.artworkUri != null) { if (metadata.artworkUri != null) {
@ -597,21 +606,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, durationMs); builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, durationMs);
} }
@Nullable @Nullable RatingCompat userRatingCompat = convertToRatingCompat(metadata.userRating);
RatingCompat userRatingCompat = convertToRatingCompat(mediaItem.mediaMetadata.userRating);
if (userRatingCompat != null) { if (userRatingCompat != null) {
builder.putRating(MediaMetadataCompat.METADATA_KEY_USER_RATING, userRatingCompat); builder.putRating(MediaMetadataCompat.METADATA_KEY_USER_RATING, userRatingCompat);
} }
@Nullable @Nullable RatingCompat overallRatingCompat = convertToRatingCompat(metadata.overallRating);
RatingCompat overallRatingCompat = convertToRatingCompat(mediaItem.mediaMetadata.overallRating);
if (overallRatingCompat != null) { if (overallRatingCompat != null) {
builder.putRating(MediaMetadataCompat.METADATA_KEY_RATING, overallRatingCompat); builder.putRating(MediaMetadataCompat.METADATA_KEY_RATING, overallRatingCompat);
} }
if (mediaItem.mediaMetadata.mediaType != null) { if (metadata.mediaType != null) {
builder.putLong( builder.putLong(MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT, metadata.mediaType);
MediaConstants.EXTRAS_KEY_MEDIA_TYPE_COMPAT, mediaItem.mediaMetadata.mediaType);
} }
return builder.build(); return builder.build();

View File

@ -67,6 +67,7 @@ interface IRemoteMediaSession {
void setTimeline(String sessionId, in Bundle timeline); void setTimeline(String sessionId, in Bundle timeline);
void createAndSetFakeTimeline(String sessionId, int windowCount); void createAndSetFakeTimeline(String sessionId, int windowCount);
void setMediaMetadata(String sessionId, in Bundle metadata);
void setPlaylistMetadata(String sessionId, in Bundle metadata); void setPlaylistMetadata(String sessionId, in Bundle metadata);
void setShuffleModeEnabled(String sessionId, boolean shuffleMode); void setShuffleModeEnabled(String sessionId, boolean shuffleMode);
void setRepeatMode(String sessionId, int repeatMode); void setRepeatMode(String sessionId, int repeatMode);

View File

@ -127,6 +127,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
.setBufferedPosition(testBufferingPosition) .setBufferedPosition(testBufferingPosition)
.setPlaybackParameters(new PlaybackParameters(testSpeed)) .setPlaybackParameters(new PlaybackParameters(testSpeed))
.setTimeline(testTimeline) .setTimeline(testTimeline)
.setMediaMetadata(testMediaItems.get(testItemIndex).mediaMetadata)
.setPlaylistMetadata(testPlaylistMetadata) .setPlaylistMetadata(testPlaylistMetadata)
.setCurrentMediaItemIndex(testItemIndex) .setCurrentMediaItemIndex(testItemIndex)
.setShuffleModeEnabled(testShuffleModeEnabled) .setShuffleModeEnabled(testShuffleModeEnabled)
@ -370,6 +371,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
.setDuration(testDurationMs) .setDuration(testDurationMs)
.setPlaybackParameters(playbackParameters) .setPlaybackParameters(playbackParameters)
.setTimeline(testTimeline) .setTimeline(testTimeline)
.setMediaMetadata(testMediaItems.get(testItemIndex).mediaMetadata)
.setPlaylistMetadata(testPlaylistMetadata) .setPlaylistMetadata(testPlaylistMetadata)
.setCurrentMediaItemIndex(testItemIndex) .setCurrentMediaItemIndex(testItemIndex)
.setShuffleModeEnabled(testShuffleModeEnabled) .setShuffleModeEnabled(testShuffleModeEnabled)
@ -979,53 +981,68 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
} }
@Test @Test
public void currentMediaItemChange() throws Exception { public void onMediaItemTransition_updatesLegacyMetadataAndPlaybackState_correctModelConversion()
throws Exception {
int testItemIndex = 3; int testItemIndex = 3;
long testPosition = 1234; long testPosition = 1234;
String testDisplayTitle = "displayTitle"; String testDisplayTitle = "displayTitle";
long testDurationMs = 30_000;
List<MediaItem> testMediaItems = MediaTestUtils.createMediaItems(/* size= */ 5); List<MediaItem> testMediaItems = MediaTestUtils.createMediaItems(/* size= */ 5);
String testCurrentMediaId = testMediaItems.get(testItemIndex).mediaId;
MediaMetadata testMediaMetadata =
new MediaMetadata.Builder().setTitle(testDisplayTitle).build();
testMediaItems.set( testMediaItems.set(
testItemIndex, testItemIndex,
new MediaItem.Builder() new MediaItem.Builder()
.setMediaId(testMediaItems.get(testItemIndex).mediaId) .setMediaId(testMediaItems.get(testItemIndex).mediaId)
.setMediaMetadata(new MediaMetadata.Builder().setTitle(testDisplayTitle).build()) .setMediaMetadata(testMediaMetadata)
.build()); .build());
Timeline timeline = new PlaylistTimeline(testMediaItems); session.getMockPlayer().setTimeline(new PlaylistTimeline(testMediaItems));
session.getMockPlayer().setTimeline(timeline); session.getMockPlayer().setCurrentMediaItemIndex(testItemIndex);
session.getMockPlayer().setCurrentPosition(testPosition);
session.getMockPlayer().setDuration(testDurationMs);
session.getMockPlayer().setMediaMetadata(testMediaMetadata);
AtomicReference<MediaMetadataCompat> metadataRef = new AtomicReference<>(); AtomicReference<MediaMetadataCompat> metadataRef = new AtomicReference<>();
AtomicReference<PlaybackStateCompat> playbackStateRef = new AtomicReference<>(); AtomicReference<PlaybackStateCompat> playbackStateRef = new AtomicReference<>();
CountDownLatch latchForMetadata = new CountDownLatch(1); CountDownLatch latchForMetadata = new CountDownLatch(1);
CountDownLatch latchForPlaybackState = new CountDownLatch(1); CountDownLatch latchForPlaybackState = new CountDownLatch(1);
List<String> callbackOrder = new ArrayList<>();
MediaControllerCompat.Callback callback = MediaControllerCompat.Callback callback =
new MediaControllerCompat.Callback() { new MediaControllerCompat.Callback() {
@Override @Override
public void onMetadataChanged(MediaMetadataCompat metadata) { public void onMetadataChanged(MediaMetadataCompat metadata) {
metadataRef.set(metadata); metadataRef.set(metadata);
callbackOrder.add("onMetadataChanged");
latchForMetadata.countDown(); latchForMetadata.countDown();
} }
@Override @Override
public void onPlaybackStateChanged(PlaybackStateCompat state) { public void onPlaybackStateChanged(PlaybackStateCompat state) {
playbackStateRef.set(state); playbackStateRef.set(state);
callbackOrder.add("onPlaybackStateChanged");
latchForPlaybackState.countDown(); latchForPlaybackState.countDown();
} }
}; };
controllerCompat.registerCallback(callback, handler); controllerCompat.registerCallback(callback, handler);
session.getMockPlayer().setCurrentMediaItemIndex(testItemIndex);
session.getMockPlayer().setCurrentPosition(testPosition);
session session
.getMockPlayer() .getMockPlayer()
.notifyMediaItemTransition(testItemIndex, Player.MEDIA_ITEM_TRANSITION_REASON_SEEK); .notifyMediaItemTransition(testItemIndex, Player.MEDIA_ITEM_TRANSITION_REASON_SEEK);
// Assert metadata.
assertThat(latchForMetadata.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); 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); .isEqualTo(testDisplayTitle);
assertThat( assertThat(getterMetadataCompat.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE))
controllerCompat
.getMetadata()
.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE))
.isEqualTo(testDisplayTitle); .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(latchForPlaybackState.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(playbackStateRef.get().getPosition()).isEqualTo(testPosition); assertThat(playbackStateRef.get().getPosition()).isEqualTo(testPosition);
assertThat(controllerCompat.getPlaybackState().getPosition()).isEqualTo(testPosition); assertThat(controllerCompat.getPlaybackState().getPosition()).isEqualTo(testPosition);
@ -1033,6 +1050,56 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
.isEqualTo(MediaUtils.convertToQueueItemId(testItemIndex)); .isEqualTo(MediaUtils.convertToQueueItemId(testItemIndex));
assertThat(controllerCompat.getPlaybackState().getActiveQueueItemId()) assertThat(controllerCompat.getPlaybackState().getActiveQueueItemId())
.isEqualTo(MediaUtils.convertToQueueItemId(testItemIndex)); .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<MediaItem> 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<MediaMetadataCompat> 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 @Test

View File

@ -714,7 +714,11 @@ public class MediaControllerWithMediaSessionCompatTest {
MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed");
MediaMetadataCompat testMetadataCompat = MediaMetadataCompat testMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); testRemoveMediaItem.mediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
/* artworkBitmap= */ null);
session.setQueue(testQueue); session.setQueue(testQueue);
session.setMetadata(testMetadataCompat); session.setMetadata(testMetadataCompat);
MediaController controller = controllerTestRule.createController(session.getSessionToken()); MediaController controller = controllerTestRule.createController(session.getSessionToken());
@ -732,7 +736,11 @@ public class MediaControllerWithMediaSessionCompatTest {
MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed");
MediaMetadataCompat testMetadataCompat = MediaMetadataCompat testMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); testRemoveMediaItem.mediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
/* artworkBitmap= */ null);
session.setQueue(testQueue); session.setQueue(testQueue);
session.setMetadata(testMetadataCompat); session.setMetadata(testMetadataCompat);
MediaController controller = controllerTestRule.createController(session.getSessionToken()); MediaController controller = controllerTestRule.createController(session.getSessionToken());
@ -767,7 +775,11 @@ public class MediaControllerWithMediaSessionCompatTest {
MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed");
MediaMetadataCompat testMetadataCompat = MediaMetadataCompat testMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testRemoveMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); testRemoveMediaItem.mediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
/* artworkBitmap= */ null);
session.setQueue(testQueue); session.setQueue(testQueue);
session.setMetadata(testMetadataCompat); session.setMetadata(testMetadataCompat);
MediaController controller = controllerTestRule.createController(session.getSessionToken()); MediaController controller = controllerTestRule.createController(session.getSessionToken());
@ -785,7 +797,11 @@ public class MediaControllerWithMediaSessionCompatTest {
MediaMetadata testMediaMetadata = testMediaItem.mediaMetadata; MediaMetadata testMediaMetadata = testMediaItem.mediaMetadata;
MediaMetadataCompat testMediaMetadataCompat = MediaMetadataCompat testMediaMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testMediaItem, /* durationMs= */ 100L, /* artworkBitmap= */ null); testMediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
/* artworkBitmap= */ null);
session.setMetadata(testMediaMetadataCompat); session.setMetadata(testMediaMetadataCompat);
MediaController controller = controllerTestRule.createController(session.getSessionToken()); MediaController controller = controllerTestRule.createController(session.getSessionToken());
@ -803,7 +819,11 @@ public class MediaControllerWithMediaSessionCompatTest {
@Nullable Bitmap artworkBitmap = getBitmapFromMetadata(testMediaMetadata); @Nullable Bitmap artworkBitmap = getBitmapFromMetadata(testMediaMetadata);
MediaMetadataCompat testMediaMetadataCompat = MediaMetadataCompat testMediaMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testMediaItem, /* durationMs= */ 100L, artworkBitmap); testMediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
artworkBitmap);
session.setMetadata(testMediaMetadataCompat); session.setMetadata(testMediaMetadataCompat);
MediaController controller = controllerTestRule.createController(session.getSessionToken()); MediaController controller = controllerTestRule.createController(session.getSessionToken());
@ -1141,9 +1161,14 @@ public class MediaControllerWithMediaSessionCompatTest {
@Test @Test
public void setPlaybackState_fromStateBufferingToPlaying_notifiesReadyState() throws Exception { public void setPlaybackState_fromStateBufferingToPlaying_notifiesReadyState() throws Exception {
List<MediaItem> testPlaylist = MediaTestUtils.createMediaItems(/* size= */ 1); List<MediaItem> testPlaylist = MediaTestUtils.createMediaItems(/* size= */ 1);
MediaItem firstMediaItemInPlaylist = testPlaylist.get(0);
MediaMetadataCompat metadata = MediaMetadataCompat metadata =
MediaUtils.convertToMediaMetadataCompat( 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; long testBufferedPosition = 5_000;
session.setMetadata(metadata); session.setMetadata(metadata);
session.setPlaybackState( session.setPlaybackState(
@ -1186,9 +1211,14 @@ public class MediaControllerWithMediaSessionCompatTest {
public void setPlaybackState_fromStatePlayingToBuffering_notifiesBufferingState() public void setPlaybackState_fromStatePlayingToBuffering_notifiesBufferingState()
throws Exception { throws Exception {
List<MediaItem> testPlaylist = MediaTestUtils.createMediaItems(1); List<MediaItem> testPlaylist = MediaTestUtils.createMediaItems(1);
MediaItem firstMediaItemInPlaylist = testPlaylist.get(0);
MediaMetadataCompat metadata = MediaMetadataCompat metadata =
MediaUtils.convertToMediaMetadataCompat( 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; long testBufferingPosition = 0;
session.setMetadata(metadata); session.setMetadata(metadata);
session.setPlaybackState( session.setPlaybackState(

View File

@ -29,6 +29,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel; import android.os.Parcel;
import android.service.media.MediaBrowserService; import android.service.media.MediaBrowserService;
@ -217,7 +218,11 @@ public final class MediaUtilsTest {
} }
MediaMetadataCompat testMediaMetadataCompat = MediaMetadataCompat testMediaMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( MediaUtils.convertToMediaMetadataCompat(
testMediaItem, /* durationMs= */ 100L, testArtworkBitmap); testMediaMetadata,
"mediaId",
Uri.parse("http://example.com"),
/* durationMs= */ 100L,
testArtworkBitmap);
MediaMetadata mediaMetadata = MediaMetadata mediaMetadata =
MediaUtils.convertToMediaMetadata(testMediaMetadataCompat, RatingCompat.RATING_NONE); MediaUtils.convertToMediaMetadata(testMediaMetadataCompat, RatingCompat.RATING_NONE);
@ -258,7 +263,11 @@ public final class MediaUtilsTest {
MediaMetadataCompat mediaMetadataCompat = MediaMetadataCompat mediaMetadataCompat =
MediaUtils.convertToMediaMetadataCompat( 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( assertThat(
mediaMetadataCompat.getLong( mediaMetadataCompat.getLong(

View File

@ -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 @Override
public void setPlaylistMetadata(String sessionId, Bundle playlistMetadataBundle) public void setPlaylistMetadata(String sessionId, Bundle playlistMetadataBundle)
throws RemoteException { throws RemoteException {

View File

@ -360,6 +360,10 @@ public class RemoteMediaSession {
binder.setTrackSelectionParameters(sessionId, parameters.toBundle()); binder.setTrackSelectionParameters(sessionId, parameters.toBundle());
} }
public void setMediaMetadata(MediaMetadata mediaMetadata) throws RemoteException {
binder.setMediaMetadata(sessionId, mediaMetadata.toBundle());
}
public void notifyTimelineChanged(@Player.TimelineChangeReason int reason) public void notifyTimelineChanged(@Player.TimelineChangeReason int reason)
throws RemoteException { throws RemoteException {
binder.notifyTimelineChanged(sessionId, reason); binder.notifyTimelineChanged(sessionId, reason);