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 5e8ae125918..516dcf10d66 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionLegacyStub.java @@ -89,11 +89,14 @@ import com.google.common.util.concurrent.Futures; 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.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; import org.checkerframework.checker.initialization.qual.Initialized; +import org.checkerframework.checker.nullness.compatqual.NullableType; // Getting the commands from MediaControllerCompat' /* package */ class MediaSessionLegacyStub extends MediaSessionCompat.Callback { @@ -394,7 +397,7 @@ public void onSkipToQueueItem(long queueId) { controller -> { PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper(); // Use queueId as an index as we've published {@link QueueItem} as so. - // see: {@link MediaUtils#convertToQueueItemList}. + // see: {@link MediaUtils#convertToQueueItem}. playerWrapper.seekToDefaultPosition((int) queueId); }, sessionCompat.getCurrentControllerInfo()); @@ -1011,8 +1014,59 @@ public void onTimelineChanged( setQueue(sessionCompat, null); return; } + + updateQueue(timeline); + + // Duration might be unknown at onMediaItemTransition and become available afterward. + updateMetadataIfChanged(); + } + + private void updateQueue(Timeline timeline) { List mediaItemList = MediaUtils.convertToMediaItemList(timeline); - List queueItemList = MediaUtils.convertToQueueItemList(mediaItemList); + List<@NullableType ListenableFuture> bitmapFutures = new ArrayList<>(); + final AtomicInteger resultCount = new AtomicInteger(0); + Runnable handleBitmapFuturesTask = + () -> { + int completedBitmapFutureCount = resultCount.incrementAndGet(); + if (completedBitmapFutureCount == mediaItemList.size()) { + handleBitmapFuturesAllCompletedAndSetQueue(bitmapFutures, timeline, mediaItemList); + } + }; + + for (int i = 0; i < mediaItemList.size(); i++) { + MediaItem mediaItem = mediaItemList.get(i); + MediaMetadata metadata = mediaItem.mediaMetadata; + if (metadata.artworkData == null) { + bitmapFutures.add(null); + handleBitmapFuturesTask.run(); + } else { + ListenableFuture bitmapFuture = + sessionImpl.getBitmapLoader().decodeBitmap(metadata.artworkData); + bitmapFutures.add(bitmapFuture); + bitmapFuture.addListener( + handleBitmapFuturesTask, sessionImpl.getApplicationHandler()::post); + } + } + } + + private void handleBitmapFuturesAllCompletedAndSetQueue( + List<@NullableType ListenableFuture> bitmapFutures, + Timeline timeline, + List mediaItems) { + List queueItemList = new ArrayList<>(); + for (int i = 0; i < bitmapFutures.size(); i++) { + @Nullable ListenableFuture future = bitmapFutures.get(i); + @Nullable Bitmap bitmap = null; + if (future != null) { + try { + bitmap = Futures.getDone(future); + } catch (CancellationException | ExecutionException e) { + Log.d(TAG, "Failed to get bitmap"); + } + } + queueItemList.add(MediaUtils.convertToQueueItem(mediaItems.get(i), i, bitmap)); + } + if (Util.SDK_INT < 21) { // In order to avoid TransactionTooLargeException for below API 21, we need to // cut the list so that it doesn't exceed the binder transaction limit. @@ -1029,9 +1083,6 @@ public void onTimelineChanged( // which means we can safely send long lists. sessionCompat.setQueue(queueItemList); } - - // Duration might be unknown at onMediaItemTransition and become available afterward. - updateMetadataIfChanged(); } @Override 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 3f89c5dd737..97d240032c9 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaUtils.java @@ -230,18 +230,14 @@ public static List convertToMediaItemList(Timeline timeline) { } /** - * Converts a list of {@link MediaItem} to a list of {@link QueueItem}. The index of the item + * Converts a {@link MediaItem} to a {@link QueueItem}. The index of the item in the playlist * would be used as the queue ID to match the behavior of {@link MediaController}. */ - public static List convertToQueueItemList(List items) { - List result = new ArrayList<>(); - for (int i = 0; i < items.size(); i++) { - MediaItem item = items.get(i); - MediaDescriptionCompat description = convertToMediaDescriptionCompat(item); - long id = convertToQueueItemId(i); - result.add(new QueueItem(description, id)); - } - return result; + public static QueueItem convertToQueueItem( + MediaItem item, int mediaItemIndex, @Nullable Bitmap artworkBitmap) { + MediaDescriptionCompat description = convertToMediaDescriptionCompat(item, artworkBitmap); + long id = convertToQueueItemId(mediaItemIndex); + return new QueueItem(description, id); } /** Converts the index of a {@link MediaItem} in a playlist into id of {@link QueueItem}. */ 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 3d4084434bd..77d06b72449 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 @@ -1121,7 +1121,7 @@ public void onQueueChanged(List queue) { MediaItem mediaItem = new MediaItem.Builder() .setMediaId("mediaItem_withSampleMediaMetadata") - .setMediaMetadata(MediaTestUtils.createMediaMetadata()) + .setMediaMetadata(MediaTestUtils.createMediaMetadataWithArtworkData()) .build(); Timeline timeline = new PlaylistTimeline(ImmutableList.of(mediaItem)); @@ -1140,6 +1140,7 @@ public void onQueueChanged(List queue) { .isTrue(); assertThat(description.getIconUri()).isEqualTo(mediaItem.mediaMetadata.artworkUri); assertThat(description.getMediaUri()).isEqualTo(mediaItem.requestMetadata.mediaUri); + assertThat(description.getIconBitmap()).isNotNull(); assertThat(TestUtils.equals(description.getExtras(), mediaItem.mediaMetadata.extras)).isTrue(); } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerMediaSessionCompatCallbackAggregationTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerMediaSessionCompatCallbackAggregationTest.java index f090ca8b9ca..6f5697fc346 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerMediaSessionCompatCallbackAggregationTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerMediaSessionCompatCallbackAggregationTest.java @@ -26,8 +26,11 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import android.content.Context; +import android.graphics.Bitmap; +import android.support.v4.media.MediaDescriptionCompat; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.RatingCompat; import android.support.v4.media.session.MediaSessionCompat; @@ -42,6 +45,7 @@ import androidx.media3.common.Player.PositionInfo; import androidx.media3.common.Timeline; import androidx.media3.common.Timeline.Window; +import androidx.media3.common.util.Util; import androidx.media3.test.session.common.HandlerThreadTestRule; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -73,11 +77,13 @@ public class MediaControllerMediaSessionCompatCallbackAggregationTest { private Context context; private RemoteMediaSessionCompat session; + private BitmapLoader bitmapLoader; @Before public void setUp() throws Exception { context = ApplicationProvider.getApplicationContext(); session = new RemoteMediaSessionCompat(DEFAULT_TEST_NAME, context); + bitmapLoader = new CacheBitmapLoader(new SimpleBitmapLoader()); } @After @@ -88,8 +94,8 @@ public void cleanUp() throws Exception { @Test public void getters_withValidQueueAndQueueIdAndMetadata() throws Exception { int testSize = 3; - List testMediaItems = MediaTestUtils.createMediaItems(testSize); - List testQueue = MediaUtils.convertToQueueItemList(testMediaItems); + List testMediaItems = MediaTestUtils.createMediaItemsWithArtworkData(testSize); + List testQueue = convertToQueueItems(testMediaItems); int testMediaItemIndex = 1; MediaMetadataCompat testMediaMetadataCompat = createMediaMetadataCompat(); @RatingCompat.Style int testRatingType = RatingCompat.RATING_HEART; @@ -173,8 +179,28 @@ public void onEvents(Player player, Events events) { assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); assertThat(mediaItemRef.get()).isEqualTo(testCurrentMediaItem); for (int i = 0; i < timelineRef.get().getWindowCount(); i++) { - assertThat(timelineRef.get().getWindow(i, new Window()).mediaItem) - .isEqualTo(i == testMediaItemIndex ? testCurrentMediaItem : testMediaItems.get(i)); + MediaItem mediaItem = timelineRef.get().getWindow(i, new Window()).mediaItem; + MediaItem expectedMediaItem = + (i == testMediaItemIndex) ? testCurrentMediaItem : testMediaItems.get(i); + if (Util.SDK_INT < 21) { + // Bitmap conversion and back gives not exactly the same byte array below API 21 + MediaMetadata mediaMetadata = + mediaItem + .mediaMetadata + .buildUpon() + .setArtworkData(/* artworkData= */ null, /* artworkDataType= */ null) + .build(); + MediaMetadata expectedMediaMetadata = + expectedMediaItem + .mediaMetadata + .buildUpon() + .setArtworkData(/* artworkData= */ null, /* artworkDataType= */ null) + .build(); + mediaItem = mediaItem.buildUpon().setMediaMetadata(mediaMetadata).build(); + expectedMediaItem = + expectedMediaItem.buildUpon().setMediaMetadata(expectedMediaMetadata).build(); + } + assertThat(mediaItem).isEqualTo(expectedMediaItem); } assertThat(timelineChangeReasonRef.get()).isEqualTo(TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED); assertThat(mediaItemTransitionReasonRef.get()) @@ -202,7 +228,7 @@ public void onEvents(Player player, Events events) { public void getters_withValidQueueAndMetadataButWithInvalidQueueId() throws Exception { int testSize = 3; List testMediaItems = MediaTestUtils.createMediaItems(testSize); - List testQueue = MediaUtils.convertToQueueItemList(testMediaItems); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testMediaItems); MediaMetadataCompat testMediaMetadataCompat = createMediaMetadataCompat(); @RatingCompat.Style int testRatingType = RatingCompat.RATING_HEART; MediaMetadata testMediaMetadata = @@ -306,7 +332,7 @@ public void onEvents(Player player, Events events) { public void getters_withValidQueueAndQueueIdWithoutMetadata() throws Exception { int testSize = 3; List testMediaItems = MediaTestUtils.createMediaItems(testSize); - List testQueue = MediaUtils.convertToQueueItemList(testMediaItems); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testMediaItems); @RatingCompat.Style int testRatingType = RatingCompat.RATING_HEART; Events testEvents = new Events( @@ -511,4 +537,18 @@ private static void assertTimelineEqualsToMediaItems( .isEqualTo(mediaItems.get(i)); } } + + private List convertToQueueItems(List mediaItems) + throws Exception { + List list = new ArrayList<>(); + for (int i = 0; i < mediaItems.size(); i++) { + MediaItem item = mediaItems.get(i); + @Nullable + Bitmap bitmap = bitmapLoader.decodeBitmap(item.mediaMetadata.artworkData).get(10, SECONDS); + MediaDescriptionCompat description = MediaUtils.convertToMediaDescriptionCompat(item, bitmap); + long id = MediaUtils.convertToQueueItemId(i); + list.add(new MediaSessionCompat.QueueItem(description, id)); + } + return list; + } } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerStateMaskingWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerStateMaskingWithMediaSessionCompatTest.java index e0c56563f7c..e10dd5ae963 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerStateMaskingWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerStateMaskingWithMediaSessionCompatTest.java @@ -418,7 +418,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void seekTo_withNewMediaItemIndex() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(3); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long initialPosition = 8_000; long initialBufferedPosition = 9_200; int initialIndex = 0; @@ -701,7 +701,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void addMediaItems() throws Exception { List mediaItems = MediaTestUtils.createMediaItems("a", "b", "c"); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int testCurrentMediaItemIndex = 1; MediaItem testCurrentMediaItem = mediaItems.get(testCurrentMediaItemIndex); @@ -767,7 +767,7 @@ public void onEvents(Player player, Player.Events events) { public void addMediaItems_beforeCurrentMediaItemIndex_shiftsCurrentMediaItemIndex() throws Exception { List mediaItems = MediaTestUtils.createMediaItems("a", "b", "c"); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int initialMediaItemIndex = 2; MediaItem testCurrentMediaItem = mediaItems.get(initialMediaItemIndex); @@ -833,7 +833,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void removeMediaItems() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(5); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int testCurrentMediaItemIndex = 0; MediaItem testCurrentMediaItem = mediaItems.get(testCurrentMediaItemIndex); @@ -898,7 +898,7 @@ public void onEvents(Player player, Player.Events events) { public void removeMediaItems_beforeCurrentMediaItemIndex_shiftsCurrentMediaItemIndex() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(5); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int initialMediaItemIndex = 4; MediaItem testCurrentMediaItem = mediaItems.get(initialMediaItemIndex); @@ -963,7 +963,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void removeMediaItems_includeCurrentMediaItem_movesCurrentItem() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(5); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int initialMediaItemIndex = 2; MediaItem testCurrentMediaItem = mediaItems.get(initialMediaItemIndex); @@ -1025,7 +1025,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void moveMediaItems() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(5); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int testCurrentMediaItemIndex = 0; MediaItem testCurrentMediaItem = mediaItems.get(testCurrentMediaItemIndex); @@ -1090,7 +1090,7 @@ public void onEvents(Player player, Player.Events events) { @Test public void moveMediaItems_withMovingCurrentMediaItem_changesCurrentItem() throws Exception { List mediaItems = MediaTestUtils.createMediaItems(5); - List queue = MediaUtils.convertToQueueItemList(mediaItems); + List queue = MediaTestUtils.convertToQueueItemsWithoutBitmap(mediaItems); long testPosition = 200L; int initialCurrentMediaItemIndex = 1; session.setPlaybackState( 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 724c82492bf..b735477ce79 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 @@ -106,6 +106,8 @@ public class MediaControllerWithMediaSessionCompatTest { @ClassRule public static MainLooperTestRule mainLooperTestRule = new MainLooperTestRule(); + private static final String TEST_IMAGE_PATH = "media/png/non-motion-photo-shortened.png"; + private final HandlerThreadTestRule threadTestRule = new HandlerThreadTestRule(TAG); private final MediaControllerTestRule controllerTestRule = new MediaControllerTestRule(threadTestRule); @@ -373,12 +375,13 @@ public void onTimelineChanged( Timeline testTimeline = MediaTestUtils.createTimeline(/* windowCount= */ 2); List testQueue = - MediaUtils.convertToQueueItemList(MediaUtils.convertToMediaItemList(testTimeline)); + MediaTestUtils.convertToQueueItemsWithoutBitmap( + MediaUtils.convertToMediaItemList(testTimeline)); session.setQueue(testQueue); assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); MediaTestUtils.assertMediaIdEquals(testTimeline, timelineFromParamRef.get()); - MediaTestUtils.assertMediaIdEquals(testTimeline, timelineFromParamRef.get()); + MediaTestUtils.assertMediaIdEquals(testTimeline, timelineFromGetterRef.get()); assertThat(reasonRef.get()).isEqualTo(Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED); } @@ -386,7 +389,8 @@ public void onTimelineChanged( public void setQueue_withNull_notifiesEmptyTimeline() throws Exception { Timeline timeline = MediaTestUtils.createTimeline(/* windowCount= */ 2); List queue = - MediaUtils.convertToQueueItemList(MediaUtils.convertToMediaItemList(timeline)); + MediaTestUtils.convertToQueueItemsWithoutBitmap( + MediaUtils.convertToMediaItemList(timeline)); session.setQueue(queue); CountDownLatch latch = new CountDownLatch(1); @@ -433,6 +437,9 @@ public void onTimelineChanged( Uri testIconUri = Uri.parse("androidx://media3-session/icon"); Uri testMediaUri = Uri.parse("androidx://media3-session/media"); Bundle testExtras = TestUtils.createTestBundle(); + byte[] testArtworkData = + TestUtils.getByteArrayForScaledBitmap(context.getApplicationContext(), TEST_IMAGE_PATH); + @Nullable Bitmap testBitmap = bitmapLoader.decodeBitmap(testArtworkData).get(10, SECONDS); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(testMediaId) @@ -442,6 +449,7 @@ public void onTimelineChanged( .setIconUri(testIconUri) .setMediaUri(testMediaUri) .setExtras(testExtras) + .setIconBitmap(testBitmap) .build(); QueueItem queueItem = new QueueItem(description, /* id= */ 0); session.setQueue(ImmutableList.of(queueItem)); @@ -455,6 +463,10 @@ public void onTimelineChanged( assertThat(TextUtils.equals(metadata.subtitle, testSubtitle)).isTrue(); assertThat(TextUtils.equals(metadata.description, testDescription)).isTrue(); assertThat(metadata.artworkUri).isEqualTo(testIconUri); + if (Util.SDK_INT >= 21) { + // Bitmap conversion and back gives not exactly the same byte array below API 21 + assertThat(metadata.artworkData).isEqualTo(testArtworkData); + } if (Util.SDK_INT < 21 || Util.SDK_INT >= 23) { // TODO(b/199055952): Test mediaUri for all API levels once the bug is fixed. assertThat(mediaItem.requestMetadata.mediaUri).isEqualTo(testMediaUri); @@ -579,7 +591,7 @@ public void onPositionDiscontinuity( public void seekToDefaultPosition_withMediaItemIndex_updatesExpectedMediaItemIndex() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setPlaybackState(/* state= */ null); int testMediaItemIndex = 2; @@ -613,7 +625,7 @@ public void onPositionDiscontinuity( @Test public void seekTo_withMediaItemIndex_updatesExpectedMediaItemIndex() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setPlaybackState(/* state= */ null); long testPositionMs = 23L; @@ -652,7 +664,7 @@ public void onPositionDiscontinuity( @Test public void getMediaItemCount_withValidQueueAndQueueId_returnsQueueSize() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setPlaybackState( new PlaybackStateCompat.Builder() @@ -686,7 +698,7 @@ public void getMediaItemCount_withoutQueueButEmptyMetadata_returnsOne() throws E public void getMediaItemCount_withInvalidQueueIdWithoutMetadata_returnsAdjustedCount() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); MediaController controller = controllerTestRule.createController(session.getSessionToken()); @@ -698,7 +710,7 @@ public void getMediaItemCount_withInvalidQueueIdWithoutMetadata_returnsAdjustedC public void getMediaItemCount_withInvalidQueueIdWithMetadata_returnsAdjustedCount() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( @@ -716,7 +728,7 @@ public void getMediaItemCount_withInvalidQueueIdWithMetadata_returnsAdjustedCoun public void getMediaItemCount_whenQueueIdIsChangedFromInvalidToValid_returnOriginalCount() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( @@ -751,7 +763,7 @@ public void onTimelineChanged( public void getCurrentMediaItemIndex_withInvalidQueueIdWithMetadata_returnsEndOfList() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); MediaItem testRemoveMediaItem = MediaTestUtils.createMediaItem("removed"); MediaMetadataCompat testMetadataCompat = MediaUtils.convertToMediaMetadataCompat( @@ -888,7 +900,7 @@ public void getMediaMetadata_withMediaMetadataCompatWithQueue_returnsMediaMetada public void getMediaMetadata_withoutMediaMetadataCompatWithQueue_returnsEmptyMediaMetadata() throws Exception { List testList = MediaTestUtils.createMediaItems(3); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); int testIndex = 1; long testActiveQueueId = testQueue.get(testIndex).getQueueId(); session.setQueue(testQueue); @@ -904,7 +916,7 @@ public void getMediaMetadata_withoutMediaMetadataCompatWithQueue_returnsEmptyMed @Test public void setPlaybackState_withActiveQueueItemId_notifiesCurrentMediaItem() throws Exception { List testList = MediaTestUtils.createMediaItems(/* size= */ 2); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder(); diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java index 45ee44b3af6..82e4008c4a1 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionCompatCallbackWithMediaControllerTest.java @@ -120,7 +120,7 @@ private RemoteMediaController createControllerAndWaitConnection() throws Excepti @Test public void play() throws Exception { List testList = MediaTestUtils.createMediaItems(/* size= */ 2); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); setPlaybackState(PlaybackStateCompat.STATE_PAUSED); @@ -135,7 +135,7 @@ public void play() throws Exception { @Test public void pause() throws Exception { List testList = MediaTestUtils.createMediaItems(/* size= */ 2); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); setPlaybackState(PlaybackStateCompat.STATE_PLAYING); @@ -150,7 +150,7 @@ public void pause() throws Exception { @Test public void prepare() throws Exception { List testList = MediaTestUtils.createMediaItems(/* size= */ 2); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); RemoteMediaController controller = createControllerAndWaitConnection(); @@ -165,7 +165,7 @@ public void prepare() throws Exception { @Test public void stop() throws Exception { List testList = MediaTestUtils.createMediaItems(/* size= */ 2); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); RemoteMediaController controller = createControllerAndWaitConnection(); @@ -328,7 +328,7 @@ public void setPlaybackParameters_withDefault_notifiesOnSetPlaybackSpeedWithDefa public void addMediaItems() throws Exception { int size = 2; List testList = MediaTestUtils.createMediaItems(size); - List testQueue = MediaUtils.convertToQueueItemList(testList); + List testQueue = MediaTestUtils.convertToQueueItemsWithoutBitmap(testList); session.setQueue(testQueue); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); @@ -355,7 +355,7 @@ public void removeMediaItems() throws Exception { int toIndex = 3; int count = toIndex - fromIndex; - session.setQueue(MediaUtils.convertToQueueItemList(testList)); + session.setQueue(MediaTestUtils.convertToQueueItemsWithoutBitmap(testList)); session.setFlags(FLAG_HANDLES_QUEUE_COMMANDS); setPlaybackState(PlaybackStateCompat.STATE_BUFFERING); RemoteMediaController controller = createControllerAndWaitConnection(); 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 d7a8fca105d..8ff1473cbc2 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 @@ -109,15 +109,21 @@ public void convertBrowserItemListToMediaItemList() { } @Test - public void convertToQueueItemList() { - int size = 3; - List mediaItems = MediaTestUtils.createMediaItems(size); - List queueItems = MediaUtils.convertToQueueItemList(mediaItems); - assertThat(queueItems).hasSize(mediaItems.size()); - for (int i = 0; i < size; ++i) { - assertThat(queueItems.get(i).getDescription().getMediaId()) - .isEqualTo(mediaItems.get(i).mediaId); - } + public void convertToQueueItem_withArtworkData() throws Exception { + MediaItem mediaItem = MediaTestUtils.createMediaItemWithArtworkData("testId"); + MediaMetadata mediaMetadata = mediaItem.mediaMetadata; + ListenableFuture bitmapFuture = bitmapLoader.decodeBitmap(mediaMetadata.artworkData); + @Nullable Bitmap bitmap = bitmapFuture.get(10, SECONDS); + + MediaSessionCompat.QueueItem queueItem = + MediaUtils.convertToQueueItem( + mediaItem, + /** mediaItemIndex= */ + 100, + bitmap); + + assertThat(queueItem.getQueueId()).isEqualTo(100); + assertThat(queueItem.getDescription().getIconBitmap()).isNotNull(); } @Test diff --git a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaTestUtils.java b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaTestUtils.java index 2b1cd045ce7..5d9e56a7c70 100644 --- a/libraries/test_session_current/src/main/java/androidx/media3/session/MediaTestUtils.java +++ b/libraries/test_session_current/src/main/java/androidx/media3/session/MediaTestUtils.java @@ -115,6 +115,28 @@ public static MediaMetadata createMediaMetadata() { .build(); } + public static MediaMetadata createMediaMetadataWithArtworkData() { + MediaMetadata.Builder mediaMetadataBuilder = + new MediaMetadata.Builder() + .setFolderType(MediaMetadata.FOLDER_TYPE_NONE) + .setIsPlayable(false) + .setTitle(METADATA_TITLE) + .setSubtitle(METADATA_SUBTITLE) + .setDescription(METADATA_DESCRIPTION) + .setArtworkUri(METADATA_ARTWORK_URI) + .setExtras(METADATA_EXTRAS); + + try { + byte[] artworkData = + TestUtils.getByteArrayForScaledBitmap( + ApplicationProvider.getApplicationContext(), TEST_IMAGE_PATH); + mediaMetadataBuilder.setArtworkData(artworkData, MediaMetadata.PICTURE_TYPE_FRONT_COVER); + } catch (IOException e) { + fail(e.getMessage()); + } + return mediaMetadataBuilder.build(); + } + public static List getTestControllerInfos(MediaSession session) { List infos = new ArrayList<>(); if (session != null) { @@ -163,6 +185,18 @@ public static List createQueueItems(int size) { return list; } + public static List convertToQueueItemsWithoutBitmap( + List mediaItems) { + List list = new ArrayList<>(); + for (int i = 0; i < mediaItems.size(); i++) { + MediaItem item = mediaItems.get(i); + MediaDescriptionCompat description = MediaUtils.convertToMediaDescriptionCompat(item, null); + long id = MediaUtils.convertToQueueItemId(i); + list.add(new MediaSessionCompat.QueueItem(description, id)); + } + return list; + } + public static Timeline createTimeline(int windowCount) { return new PlaylistTimeline(createMediaItems(/* size= */ windowCount)); }