Use onMediaMetadataChanged for updating the legacy session
Issue: androidx/media#219 PiperOrigin-RevId: 501080612
This commit is contained in:
parent
9882a20783
commit
375299bf36
@ -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.
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user