From 052c4b3c1a6b72efd7fcbf433c646fed9ea91748 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 19 Jan 2023 16:32:14 +0000 Subject: [PATCH] Add command check for metadata in DefaultMediaNotificationProvider PiperOrigin-RevId: 503172986 --- .../DefaultMediaNotificationProvider.java | 54 ++++++++++--------- .../DefaultMediaNotificationProviderTest.java | 45 +++++++++++++++- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java b/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java index c3acb2a83d4..6b2368df7dd 100644 --- a/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java +++ b/libraries/session/src/main/java/androidx/media3/session/DefaultMediaNotificationProvider.java @@ -319,33 +319,35 @@ public final MediaNotification createNotification( mediaStyle.setShowActionsInCompactView(compactViewIndices); // Set metadata info in the notification. - MediaMetadata metadata = player.getMediaMetadata(); - builder - .setContentTitle(getNotificationContentTitle(metadata)) - .setContentText(getNotificationContentText(metadata)); - @Nullable - ListenableFuture bitmapFuture = - mediaSession.getBitmapLoader().loadBitmapFromMetadata(metadata); - if (bitmapFuture != null) { - if (pendingOnBitmapLoadedFutureCallback != null) { - pendingOnBitmapLoadedFutureCallback.discardIfPending(); - } - if (bitmapFuture.isDone()) { - try { - builder.setLargeIcon(Futures.getDone(bitmapFuture)); - } catch (ExecutionException e) { - Log.w(TAG, getBitmapLoadErrorMessage(e)); + if (player.isCommandAvailable(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)) { + MediaMetadata metadata = player.getMediaMetadata(); + builder + .setContentTitle(getNotificationContentTitle(metadata)) + .setContentText(getNotificationContentText(metadata)); + @Nullable + ListenableFuture bitmapFuture = + mediaSession.getBitmapLoader().loadBitmapFromMetadata(metadata); + if (bitmapFuture != null) { + if (pendingOnBitmapLoadedFutureCallback != null) { + pendingOnBitmapLoadedFutureCallback.discardIfPending(); + } + if (bitmapFuture.isDone()) { + try { + builder.setLargeIcon(Futures.getDone(bitmapFuture)); + } catch (ExecutionException e) { + Log.w(TAG, getBitmapLoadErrorMessage(e)); + } + } else { + pendingOnBitmapLoadedFutureCallback = + new OnBitmapLoadedFutureCallback( + notificationId, builder, onNotificationChangedCallback); + Futures.addCallback( + bitmapFuture, + pendingOnBitmapLoadedFutureCallback, + // This callback must be executed on the next looper iteration, after this method has + // returned a media notification. + mainHandler::post); } - } else { - pendingOnBitmapLoadedFutureCallback = - new OnBitmapLoadedFutureCallback( - notificationId, builder, onNotificationChangedCallback); - Futures.addCallback( - bitmapFuture, - pendingOnBitmapLoadedFutureCallback, - // This callback must be executed on the next looper iteration, after this method has - // returned a media notification. - mainHandler::post); } } diff --git a/libraries/session/src/test/java/androidx/media3/session/DefaultMediaNotificationProviderTest.java b/libraries/session/src/test/java/androidx/media3/session/DefaultMediaNotificationProviderTest.java index 8b54ccca87c..fbc51af2990 100644 --- a/libraries/session/src/test/java/androidx/media3/session/DefaultMediaNotificationProviderTest.java +++ b/libraries/session/src/test/java/androidx/media3/session/DefaultMediaNotificationProviderTest.java @@ -20,6 +20,7 @@ import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -629,6 +630,33 @@ public void setMediaMetadataArtist_notificationUsesItAsContentText() { assertThat(isMediaMetadataArtistEqualToNotificationContentText).isTrue(); } + @Test + public void + setMediaMetadata_withoutAvailableCommandToGetMetadata_doesNotUseMetadataForNotification() { + Context context = ApplicationProvider.getApplicationContext(); + DefaultMediaNotificationProvider defaultMediaNotificationProvider = + new DefaultMediaNotificationProvider.Builder(context).build(); + DefaultActionFactory defaultActionFactory = + new DefaultActionFactory(Robolectric.setupService(TestService.class)); + MediaSession mockMediaSession = + createMockMediaSessionForNotification( + new MediaMetadata.Builder().setArtist("artist").setTitle("title").build(), + /* getMetadataCommandAvailable= */ false); + BitmapLoader mockBitmapLoader = mock(BitmapLoader.class); + when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null); + when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader); + + MediaNotification notification = + defaultMediaNotificationProvider.createNotification( + mockMediaSession, + ImmutableList.of(), + defaultActionFactory, + mock(MediaNotification.Provider.Callback.class)); + + assertThat(NotificationCompat.getContentText(notification.notification)).isNull(); + assertThat(NotificationCompat.getContentTitle(notification.notification)).isNull(); + } + /** * {@link DefaultMediaNotificationProvider} is designed to be extendable. Public constructor * should not be removed. @@ -721,9 +749,22 @@ private static void assertHasNotificationChannel( } private static MediaSession createMockMediaSessionForNotification(MediaMetadata mediaMetadata) { + return createMockMediaSessionForNotification( + mediaMetadata, /* getMetadataCommandAvailable= */ true); + } + + private static MediaSession createMockMediaSessionForNotification( + MediaMetadata mediaMetadata, boolean getMetadataCommandAvailable) { Player mockPlayer = mock(Player.class); - when(mockPlayer.getAvailableCommands()).thenReturn(Commands.EMPTY); - when(mockPlayer.getMediaMetadata()).thenReturn(mediaMetadata); + when(mockPlayer.isCommandAvailable(anyInt())).thenReturn(false); + if (getMetadataCommandAvailable) { + when(mockPlayer.getAvailableCommands()) + .thenReturn(new Commands.Builder().add(Player.COMMAND_GET_MEDIA_ITEMS_METADATA).build()); + when(mockPlayer.isCommandAvailable(Player.COMMAND_GET_MEDIA_ITEMS_METADATA)).thenReturn(true); + when(mockPlayer.getMediaMetadata()).thenReturn(mediaMetadata); + } else { + when(mockPlayer.getAvailableCommands()).thenReturn(Commands.EMPTY); + } MediaSession mockMediaSession = mock(MediaSession.class); when(mockMediaSession.getPlayer()).thenReturn(mockPlayer); MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);