mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Mark MediaSession methods final to prevent accidental overrides
It's currently not possible to even subclass MediaSession because the constructor is package-private. To avoid any accidental usage or future indirect subclassing, all methods can be marked as final. PiperOrigin-RevId: 521775373
This commit is contained in:
parent
28aa5e847b
commit
ff919fe74d
30
api.txt
30
api.txt
@ -1625,21 +1625,21 @@ package androidx.media3.session {
|
|||||||
field @IntRange(from=1) public final int notificationId;
|
field @IntRange(from=1) public final int notificationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MediaSession {
|
@com.google.errorprone.annotations.DoNotMock public class MediaSession {
|
||||||
method public void broadcastCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle);
|
method public final void broadcastCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle);
|
||||||
method public java.util.List<androidx.media3.session.MediaSession.ControllerInfo> getConnectedControllers();
|
method public final java.util.List<androidx.media3.session.MediaSession.ControllerInfo> getConnectedControllers();
|
||||||
method public String getId();
|
method public final String getId();
|
||||||
method public androidx.media3.common.Player getPlayer();
|
method public final androidx.media3.common.Player getPlayer();
|
||||||
method @Nullable public android.app.PendingIntent getSessionActivity();
|
method @Nullable public final android.app.PendingIntent getSessionActivity();
|
||||||
method public androidx.media3.session.SessionToken getToken();
|
method public final androidx.media3.session.SessionToken getToken();
|
||||||
method public void release();
|
method public final void release();
|
||||||
method public com.google.common.util.concurrent.ListenableFuture<androidx.media3.session.SessionResult> sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle);
|
method public final com.google.common.util.concurrent.ListenableFuture<androidx.media3.session.SessionResult> sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommand, android.os.Bundle);
|
||||||
method public void setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands);
|
method public final void setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo, androidx.media3.session.SessionCommands, androidx.media3.common.Player.Commands);
|
||||||
method public com.google.common.util.concurrent.ListenableFuture<androidx.media3.session.SessionResult> setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo, java.util.List<androidx.media3.session.CommandButton>);
|
method public final com.google.common.util.concurrent.ListenableFuture<androidx.media3.session.SessionResult> setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo, java.util.List<androidx.media3.session.CommandButton>);
|
||||||
method public void setCustomLayout(java.util.List<androidx.media3.session.CommandButton>);
|
method public final void setCustomLayout(java.util.List<androidx.media3.session.CommandButton>);
|
||||||
method public void setPlayer(androidx.media3.common.Player);
|
method public final void setPlayer(androidx.media3.common.Player);
|
||||||
method public void setSessionExtras(android.os.Bundle);
|
method public final void setSessionExtras(android.os.Bundle);
|
||||||
method public void setSessionExtras(androidx.media3.session.MediaSession.ControllerInfo, android.os.Bundle);
|
method public final void setSessionExtras(androidx.media3.session.MediaSession.ControllerInfo, android.os.Bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class MediaSession.Builder {
|
public static final class MediaSession.Builder {
|
||||||
|
@ -43,6 +43,7 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.multidex:multidex:' + androidxMultidexVersion
|
androidTestImplementation 'androidx.multidex:multidex:' + androidxMultidexVersion
|
||||||
androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion
|
androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion
|
||||||
testImplementation project(modulePrefix + 'test-utils')
|
testImplementation project(modulePrefix + 'test-utils')
|
||||||
|
testImplementation project(modulePrefix + 'lib-exoplayer')
|
||||||
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
|
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.errorprone.annotations.DoNotMock;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -220,6 +221,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can
|
* by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can
|
||||||
* connect and an app can accept such controllers in the same way as with legacy sessions.
|
* connect and an app can accept such controllers in the same way as with legacy sessions.
|
||||||
*/
|
*/
|
||||||
|
@DoNotMock
|
||||||
public class MediaSession {
|
public class MediaSession {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -592,7 +594,7 @@ public class MediaSession {
|
|||||||
* @return The {@link PendingIntent} to launch an activity belonging to the session.
|
* @return The {@link PendingIntent} to launch an activity belonging to the session.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public PendingIntent getSessionActivity() {
|
public final PendingIntent getSessionActivity() {
|
||||||
return impl.getSessionActivity();
|
return impl.getSessionActivity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +607,7 @@ public class MediaSession {
|
|||||||
* @throws IllegalStateException if the new player's application looper differs from the current
|
* @throws IllegalStateException if the new player's application looper differs from the current
|
||||||
* looper.
|
* looper.
|
||||||
*/
|
*/
|
||||||
public void setPlayer(Player player) {
|
public final void setPlayer(Player player) {
|
||||||
checkNotNull(player);
|
checkNotNull(player);
|
||||||
checkArgument(player.canAdvertiseSession());
|
checkArgument(player.canAdvertiseSession());
|
||||||
checkArgument(player.getApplicationLooper() == getPlayer().getApplicationLooper());
|
checkArgument(player.getApplicationLooper() == getPlayer().getApplicationLooper());
|
||||||
@ -623,7 +625,7 @@ public class MediaSession {
|
|||||||
* further use the player after the session is released and needs to make sure to eventually
|
* further use the player after the session is released and needs to make sure to eventually
|
||||||
* release the player.
|
* release the player.
|
||||||
*/
|
*/
|
||||||
public void release() {
|
public final void release() {
|
||||||
try {
|
try {
|
||||||
synchronized (STATIC_LOCK) {
|
synchronized (STATIC_LOCK) {
|
||||||
SESSION_ID_TO_SESSION_MAP.remove(impl.getId());
|
SESSION_ID_TO_SESSION_MAP.remove(impl.getId());
|
||||||
@ -634,27 +636,27 @@ public class MediaSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ boolean isReleased() {
|
/* package */ final boolean isReleased() {
|
||||||
return impl.isReleased();
|
return impl.isReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the underlying {@link Player}. */
|
/** Returns the underlying {@link Player}. */
|
||||||
public Player getPlayer() {
|
public final Player getPlayer() {
|
||||||
return impl.getPlayerWrapper().getWrappedPlayer();
|
return impl.getPlayerWrapper().getWrappedPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the session ID. */
|
/** Returns the session ID. */
|
||||||
public String getId() {
|
public final String getId() {
|
||||||
return impl.getId();
|
return impl.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the {@link SessionToken} for creating {@link MediaController}. */
|
/** Returns the {@link SessionToken} for creating {@link MediaController}. */
|
||||||
public SessionToken getToken() {
|
public final SessionToken getToken() {
|
||||||
return impl.getToken();
|
return impl.getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the list of connected controllers. */
|
/** Returns the list of connected controllers. */
|
||||||
public List<ControllerInfo> getConnectedControllers() {
|
public final List<ControllerInfo> getConnectedControllers() {
|
||||||
return impl.getConnectedControllers();
|
return impl.getConnectedControllers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +707,7 @@ public class MediaSession {
|
|||||||
* @param controller The controller to specify layout.
|
* @param controller The controller to specify layout.
|
||||||
* @param layout The ordered list of {@link CommandButton}.
|
* @param layout The ordered list of {@link CommandButton}.
|
||||||
*/
|
*/
|
||||||
public ListenableFuture<SessionResult> setCustomLayout(
|
public final ListenableFuture<SessionResult> setCustomLayout(
|
||||||
ControllerInfo controller, List<CommandButton> layout) {
|
ControllerInfo controller, List<CommandButton> layout) {
|
||||||
checkNotNull(controller, "controller must not be null");
|
checkNotNull(controller, "controller must not be null");
|
||||||
checkNotNull(layout, "layout must not be null");
|
checkNotNull(layout, "layout must not be null");
|
||||||
@ -728,7 +730,7 @@ public class MediaSession {
|
|||||||
*
|
*
|
||||||
* @param layout The ordered list of {@link CommandButton}.
|
* @param layout The ordered list of {@link CommandButton}.
|
||||||
*/
|
*/
|
||||||
public void setCustomLayout(List<CommandButton> layout) {
|
public final void setCustomLayout(List<CommandButton> layout) {
|
||||||
checkNotNull(layout, "layout must not be null");
|
checkNotNull(layout, "layout must not be null");
|
||||||
impl.setCustomLayout(layout);
|
impl.setCustomLayout(layout);
|
||||||
}
|
}
|
||||||
@ -749,7 +751,7 @@ public class MediaSession {
|
|||||||
* @param sessionCommands The new available session commands.
|
* @param sessionCommands The new available session commands.
|
||||||
* @param playerCommands The new available player commands.
|
* @param playerCommands The new available player commands.
|
||||||
*/
|
*/
|
||||||
public void setAvailableCommands(
|
public final void setAvailableCommands(
|
||||||
ControllerInfo controller, SessionCommands sessionCommands, Player.Commands playerCommands) {
|
ControllerInfo controller, SessionCommands sessionCommands, Player.Commands playerCommands) {
|
||||||
checkNotNull(controller, "controller must not be null");
|
checkNotNull(controller, "controller must not be null");
|
||||||
checkNotNull(sessionCommands, "sessionCommands must not be null");
|
checkNotNull(sessionCommands, "sessionCommands must not be null");
|
||||||
@ -768,7 +770,7 @@ public class MediaSession {
|
|||||||
* @param args A {@link Bundle} for additional arguments. May be empty.
|
* @param args A {@link Bundle} for additional arguments. May be empty.
|
||||||
* @see #sendCustomCommand(ControllerInfo, SessionCommand, Bundle)
|
* @see #sendCustomCommand(ControllerInfo, SessionCommand, Bundle)
|
||||||
*/
|
*/
|
||||||
public void broadcastCustomCommand(SessionCommand command, Bundle args) {
|
public final void broadcastCustomCommand(SessionCommand command, Bundle args) {
|
||||||
checkNotNull(command);
|
checkNotNull(command);
|
||||||
checkNotNull(args);
|
checkNotNull(args);
|
||||||
checkArgument(
|
checkArgument(
|
||||||
@ -784,7 +786,7 @@ public class MediaSession {
|
|||||||
*
|
*
|
||||||
* @param sessionExtras The session extras.
|
* @param sessionExtras The session extras.
|
||||||
*/
|
*/
|
||||||
public void setSessionExtras(Bundle sessionExtras) {
|
public final void setSessionExtras(Bundle sessionExtras) {
|
||||||
checkNotNull(sessionExtras);
|
checkNotNull(sessionExtras);
|
||||||
impl.setSessionExtras(sessionExtras);
|
impl.setSessionExtras(sessionExtras);
|
||||||
}
|
}
|
||||||
@ -797,7 +799,7 @@ public class MediaSession {
|
|||||||
* @param controller The controller to send the extras to.
|
* @param controller The controller to send the extras to.
|
||||||
* @param sessionExtras The session extras.
|
* @param sessionExtras The session extras.
|
||||||
*/
|
*/
|
||||||
public void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) {
|
public final void setSessionExtras(ControllerInfo controller, Bundle sessionExtras) {
|
||||||
checkNotNull(controller, "controller must not be null");
|
checkNotNull(controller, "controller must not be null");
|
||||||
checkNotNull(sessionExtras);
|
checkNotNull(sessionExtras);
|
||||||
impl.setSessionExtras(controller, sessionExtras);
|
impl.setSessionExtras(controller, sessionExtras);
|
||||||
@ -805,7 +807,7 @@ public class MediaSession {
|
|||||||
|
|
||||||
/** Returns the {@link BitmapLoader}. */
|
/** Returns the {@link BitmapLoader}. */
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public BitmapLoader getBitmapLoader() {
|
public final BitmapLoader getBitmapLoader() {
|
||||||
return impl.getBitmapLoader();
|
return impl.getBitmapLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -823,7 +825,7 @@ public class MediaSession {
|
|||||||
* @return A {@link ListenableFuture} of {@link SessionResult} from the controller.
|
* @return A {@link ListenableFuture} of {@link SessionResult} from the controller.
|
||||||
* @see #broadcastCustomCommand(SessionCommand, Bundle)
|
* @see #broadcastCustomCommand(SessionCommand, Bundle)
|
||||||
*/
|
*/
|
||||||
public ListenableFuture<SessionResult> sendCustomCommand(
|
public final ListenableFuture<SessionResult> sendCustomCommand(
|
||||||
ControllerInfo controller, SessionCommand command, Bundle args) {
|
ControllerInfo controller, SessionCommand command, Bundle args) {
|
||||||
checkNotNull(controller);
|
checkNotNull(controller);
|
||||||
checkNotNull(command);
|
checkNotNull(command);
|
||||||
@ -834,7 +836,7 @@ public class MediaSession {
|
|||||||
return impl.sendCustomCommand(controller, command, args);
|
return impl.sendCustomCommand(controller, command, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ MediaSessionCompat getSessionCompat() {
|
/* package */ final MediaSessionCompat getSessionCompat() {
|
||||||
return impl.getSessionCompat();
|
return impl.getSessionCompat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,7 +845,7 @@ public class MediaSession {
|
|||||||
* internally by this session.
|
* internally by this session.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public MediaSessionCompat.Token getSessionCompatToken() {
|
public final MediaSessionCompat.Token getSessionCompatToken() {
|
||||||
return impl.getSessionCompat().getSessionToken();
|
return impl.getSessionCompat().getSessionToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,12 +854,12 @@ public class MediaSession {
|
|||||||
*
|
*
|
||||||
* @param timeoutMs The timeout in milliseconds.
|
* @param timeoutMs The timeout in milliseconds.
|
||||||
*/
|
*/
|
||||||
/* package */ void setLegacyControllerConnectionTimeoutMs(long timeoutMs) {
|
/* package */ final void setLegacyControllerConnectionTimeoutMs(long timeoutMs) {
|
||||||
impl.setLegacyControllerConnectionTimeoutMs(timeoutMs);
|
impl.setLegacyControllerConnectionTimeoutMs(timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handles the controller's connection request from {@link MediaSessionService}. */
|
/** Handles the controller's connection request from {@link MediaSessionService}. */
|
||||||
/* package */ void handleControllerConnectionFromService(
|
/* package */ final void handleControllerConnectionFromService(
|
||||||
IMediaController controller,
|
IMediaController controller,
|
||||||
int controllerVersion,
|
int controllerVersion,
|
||||||
int controllerInterfaceVersion,
|
int controllerInterfaceVersion,
|
||||||
@ -875,7 +877,7 @@ public class MediaSession {
|
|||||||
connectionHints);
|
connectionHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ IBinder getLegacyBrowserServiceBinder() {
|
/* package */ final IBinder getLegacyBrowserServiceBinder() {
|
||||||
return impl.getLegacyBrowserServiceBinder();
|
return impl.getLegacyBrowserServiceBinder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,21 +889,22 @@ public class MediaSession {
|
|||||||
* after an immediate one-time update.
|
* after an immediate one-time update.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
/* package */ void setSessionPositionUpdateDelayMs(long updateDelayMs) {
|
/* package */ final void setSessionPositionUpdateDelayMs(long updateDelayMs) {
|
||||||
impl.setSessionPositionUpdateDelayMsOnHandler(updateDelayMs);
|
impl.setSessionPositionUpdateDelayMsOnHandler(updateDelayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the {@linkplain Listener listener}. */
|
/** Sets the {@linkplain Listener listener}. */
|
||||||
/* package */ void setListener(Listener listener) {
|
/* package */ final void setListener(Listener listener) {
|
||||||
impl.setMediaSessionListener(listener);
|
impl.setMediaSessionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clears the {@linkplain Listener listener}. */
|
/** Clears the {@linkplain Listener listener}. */
|
||||||
/* package */ void clearListener() {
|
/* package */ final void clearListener() {
|
||||||
impl.clearMediaSessionListener();
|
impl.clearMediaSessionListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uri getUri() {
|
@VisibleForTesting
|
||||||
|
/* package */ final Uri getUri() {
|
||||||
return impl.getUri();
|
return impl.getUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,19 +16,21 @@
|
|||||||
package androidx.media3.session;
|
package androidx.media3.session;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
|
import androidx.media3.test.utils.TestExoPlayerBuilder;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
@ -38,41 +40,42 @@ import org.robolectric.shadows.ShadowPendingIntent;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class DefaultActionFactoryTest {
|
public class DefaultActionFactoryTest {
|
||||||
|
|
||||||
|
private Player player;
|
||||||
|
private MediaSession mediaSession;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
player = new TestExoPlayerBuilder(context).build();
|
||||||
|
mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createMediaPendingIntent_intentIsMediaAction() {
|
public void createMediaPendingIntent_intentIsMediaAction() {
|
||||||
DefaultActionFactory actionFactory =
|
DefaultActionFactory actionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
Uri dataUri = Uri.parse("http://example.com");
|
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Player mockPlayer = mock(Player.class);
|
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
|
||||||
when(mockMediaSession.getPlayer()).thenReturn(mockPlayer);
|
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(dataUri);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent =
|
PendingIntent pendingIntent =
|
||||||
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_SEEK_FORWARD);
|
actionFactory.createMediaActionPendingIntent(mediaSession, Player.COMMAND_SEEK_FORWARD);
|
||||||
|
|
||||||
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
||||||
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
|
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
|
||||||
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(dataUri);
|
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(mediaSession.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createMediaPendingIntent_commandPlayPauseWhenNotPlayWhenReady_isForegroundService() {
|
public void createMediaPendingIntent_commandPlayPauseWhenNotPlayWhenReady_isForegroundService() {
|
||||||
DefaultActionFactory actionFactory =
|
DefaultActionFactory actionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
Uri dataUri = Uri.parse("http://example.com");
|
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Player mockPlayer = mock(Player.class);
|
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
|
||||||
when(mockMediaSession.getPlayer()).thenReturn(mockPlayer);
|
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(dataUri);
|
|
||||||
when(mockPlayer.getPlayWhenReady()).thenReturn(false);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent =
|
PendingIntent pendingIntent =
|
||||||
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_PLAY_PAUSE);
|
actionFactory.createMediaActionPendingIntent(mediaSession, Player.COMMAND_PLAY_PAUSE);
|
||||||
|
|
||||||
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
||||||
assertThat(shadowPendingIntent.isForegroundService()).isTrue();
|
assertThat(shadowPendingIntent.isForegroundService()).isTrue();
|
||||||
@ -82,17 +85,10 @@ public class DefaultActionFactoryTest {
|
|||||||
public void createMediaPendingIntent_commandPlayPauseWhenPlayWhenReady_notAForegroundService() {
|
public void createMediaPendingIntent_commandPlayPauseWhenPlayWhenReady_notAForegroundService() {
|
||||||
DefaultActionFactory actionFactory =
|
DefaultActionFactory actionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
Uri dataUri = Uri.parse("http://example.com");
|
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Player mockPlayer = mock(Player.class);
|
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
|
||||||
when(mockMediaSession.getPlayer()).thenReturn(mockPlayer);
|
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(dataUri);
|
|
||||||
when(mockPlayer.getPlayWhenReady()).thenReturn(true);
|
|
||||||
|
|
||||||
|
player.play();
|
||||||
PendingIntent pendingIntent =
|
PendingIntent pendingIntent =
|
||||||
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_PLAY_PAUSE);
|
actionFactory.createMediaActionPendingIntent(mediaSession, Player.COMMAND_PLAY_PAUSE);
|
||||||
|
|
||||||
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
|
||||||
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
|
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
|
||||||
@ -123,11 +119,6 @@ public class DefaultActionFactoryTest {
|
|||||||
public void createCustomActionFromCustomCommandButton() {
|
public void createCustomActionFromCustomCommandButton() {
|
||||||
DefaultActionFactory actionFactory =
|
DefaultActionFactory actionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
|
||||||
Uri dataUri = Uri.parse("http://example.com");
|
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(dataUri);
|
|
||||||
Bundle commandBundle = new Bundle();
|
Bundle commandBundle = new Bundle();
|
||||||
commandBundle.putString("command-key", "command-value");
|
commandBundle.putString("command-key", "command-value");
|
||||||
Bundle buttonBundle = new Bundle();
|
Bundle buttonBundle = new Bundle();
|
||||||
@ -141,11 +132,10 @@ public class DefaultActionFactoryTest {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
NotificationCompat.Action notificationAction =
|
NotificationCompat.Action notificationAction =
|
||||||
actionFactory.createCustomActionFromCustomCommandButton(
|
actionFactory.createCustomActionFromCustomCommandButton(mediaSession, customSessionCommand);
|
||||||
mockMediaSession, customSessionCommand);
|
|
||||||
|
|
||||||
ShadowPendingIntent shadowPendingIntent = shadowOf(notificationAction.actionIntent);
|
ShadowPendingIntent shadowPendingIntent = shadowOf(notificationAction.actionIntent);
|
||||||
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(dataUri);
|
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(mediaSession.getUri());
|
||||||
assertThat(String.valueOf(notificationAction.title)).isEqualTo("name");
|
assertThat(String.valueOf(notificationAction.title)).isEqualTo("name");
|
||||||
assertThat(notificationAction.getIconCompat().getResId())
|
assertThat(notificationAction.getIconCompat().getResId())
|
||||||
.isEqualTo(R.drawable.media3_notification_pause);
|
.isEqualTo(R.drawable.media3_notification_pause);
|
||||||
@ -169,7 +159,7 @@ public class DefaultActionFactoryTest {
|
|||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() ->
|
() ->
|
||||||
actionFactory.createCustomActionFromCustomCommandButton(
|
actionFactory.createCustomActionFromCustomCommandButton(
|
||||||
mock(MediaSession.class), customSessionCommand));
|
mediaSession, customSessionCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A test service for unit tests. */
|
/** A test service for unit tests. */
|
||||||
|
@ -20,7 +20,6 @@ import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_C
|
|||||||
import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID;
|
import static androidx.media3.session.DefaultMediaNotificationProvider.DEFAULT_NOTIFICATION_ID;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
@ -39,10 +38,12 @@ import android.os.Bundle;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.media3.common.ForwardingPlayer;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.common.Player.Commands;
|
import androidx.media3.common.Player.Commands;
|
||||||
import androidx.media3.common.util.BitmapLoader;
|
import androidx.media3.common.util.BitmapLoader;
|
||||||
|
import androidx.media3.test.utils.TestExoPlayerBuilder;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@ -62,26 +63,31 @@ import org.robolectric.shadows.ShadowNotificationManager;
|
|||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class DefaultMediaNotificationProviderTest {
|
public class DefaultMediaNotificationProviderTest {
|
||||||
|
|
||||||
|
private final Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMediaButtons_playWhenReadyTrueOrFalse_correctPlayPauseResources() {
|
public void getMediaButtons_playWhenReadyTrueOrFalse_correctPlayPauseResources() {
|
||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.build();
|
.build();
|
||||||
Commands commands = new Commands.Builder().addAllCommands().build();
|
Commands commands = new Commands.Builder().addAllCommands().build();
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
List<CommandButton> mediaButtonsWhenPlaying =
|
List<CommandButton> mediaButtonsWhenPlaying =
|
||||||
defaultMediaNotificationProvider.getMediaButtons(
|
defaultMediaNotificationProvider.getMediaButtons(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
commands,
|
commands,
|
||||||
/* customLayout= */ ImmutableList.of(),
|
/* customLayout= */ ImmutableList.of(),
|
||||||
/* showPauseButton= */ true);
|
/* showPauseButton= */ true);
|
||||||
List<CommandButton> mediaButtonWhenPaused =
|
List<CommandButton> mediaButtonWhenPaused =
|
||||||
defaultMediaNotificationProvider.getMediaButtons(
|
defaultMediaNotificationProvider.getMediaButtons(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
commands,
|
commands,
|
||||||
/* customLayout= */ ImmutableList.of(),
|
/* customLayout= */ ImmutableList.of(),
|
||||||
/* showPauseButton= */ false);
|
/* showPauseButton= */ false);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(mediaButtonsWhenPlaying).hasSize(3);
|
assertThat(mediaButtonsWhenPlaying).hasSize(3);
|
||||||
assertThat(mediaButtonsWhenPlaying.get(1).playerCommand).isEqualTo(Player.COMMAND_PLAY_PAUSE);
|
assertThat(mediaButtonsWhenPlaying.get(1).playerCommand).isEqualTo(Player.COMMAND_PLAY_PAUSE);
|
||||||
@ -100,7 +106,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.build();
|
.build();
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Commands commands = new Commands.Builder().addAllCommands().build();
|
Commands commands = new Commands.Builder().addAllCommands().build();
|
||||||
SessionCommand customSessionCommand = new SessionCommand("", Bundle.EMPTY);
|
SessionCommand customSessionCommand = new SessionCommand("", Bundle.EMPTY);
|
||||||
CommandButton customCommandButton =
|
CommandButton customCommandButton =
|
||||||
@ -109,13 +114,17 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setIconResId(R.drawable.media3_icon_circular_play)
|
.setIconResId(R.drawable.media3_icon_circular_play)
|
||||||
.setSessionCommand(customSessionCommand)
|
.setSessionCommand(customSessionCommand)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
List<CommandButton> mediaButtons =
|
List<CommandButton> mediaButtons =
|
||||||
defaultMediaNotificationProvider.getMediaButtons(
|
defaultMediaNotificationProvider.getMediaButtons(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
commands,
|
commands,
|
||||||
ImmutableList.of(customCommandButton),
|
ImmutableList.of(customCommandButton),
|
||||||
/* showPauseButton= */ true);
|
/* showPauseButton= */ true);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(mediaButtons).hasSize(4);
|
assertThat(mediaButtons).hasSize(4);
|
||||||
assertThat(mediaButtons.get(0).playerCommand)
|
assertThat(mediaButtons.get(0).playerCommand)
|
||||||
@ -130,7 +139,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.build();
|
.build();
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Commands commands = new Commands.Builder().build();
|
Commands commands = new Commands.Builder().build();
|
||||||
SessionCommand customSessionCommand = new SessionCommand("action1", Bundle.EMPTY);
|
SessionCommand customSessionCommand = new SessionCommand("action1", Bundle.EMPTY);
|
||||||
CommandButton customCommandButton =
|
CommandButton customCommandButton =
|
||||||
@ -139,13 +147,17 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setIconResId(R.drawable.media3_icon_circular_play)
|
.setIconResId(R.drawable.media3_icon_circular_play)
|
||||||
.setSessionCommand(customSessionCommand)
|
.setSessionCommand(customSessionCommand)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
List<CommandButton> mediaButtons =
|
List<CommandButton> mediaButtons =
|
||||||
defaultMediaNotificationProvider.getMediaButtons(
|
defaultMediaNotificationProvider.getMediaButtons(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
commands,
|
commands,
|
||||||
ImmutableList.of(customCommandButton),
|
ImmutableList.of(customCommandButton),
|
||||||
/* showPauseButton= */ true);
|
/* showPauseButton= */ true);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(mediaButtons).containsExactly(customCommandButton);
|
assertThat(mediaButtons).containsExactly(customCommandButton);
|
||||||
}
|
}
|
||||||
@ -157,7 +169,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.build();
|
.build();
|
||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setPlayerCommand(Player.COMMAND_PLAY_PAUSE)
|
.setPlayerCommand(Player.COMMAND_PLAY_PAUSE)
|
||||||
@ -191,29 +202,33 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setSessionCommand(new SessionCommand("action4", Bundle.EMPTY))
|
.setSessionCommand(new SessionCommand("action4", Bundle.EMPTY))
|
||||||
.setExtras(commandButton4Bundle)
|
.setExtras(commandButton4Bundle)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
int[] compactViewIndices =
|
int[] compactViewIndices =
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1, commandButton2, commandButton3, commandButton4),
|
ImmutableList.of(commandButton1, commandButton2, commandButton3, commandButton4),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
mockActionFactory);
|
mockActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
verify(mockNotificationBuilder, times(4)).addAction(any());
|
verify(mockNotificationBuilder, times(4)).addAction(any());
|
||||||
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createMediaAction(
|
.createMediaAction(
|
||||||
eq(mockMediaSession), any(), eq("displayName"), eq(commandButton1.playerCommand));
|
eq(mediaSession), any(), eq("displayName"), eq(commandButton1.playerCommand));
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton2);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton2);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton3);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton3);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton4);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton4);
|
||||||
verifyNoMoreInteractions(mockActionFactory);
|
verifyNoMoreInteractions(mockActionFactory);
|
||||||
assertThat(compactViewIndices).asList().containsExactly(1, 3, 2).inOrder();
|
assertThat(compactViewIndices).asList().containsExactly(1, 3, 2).inOrder();
|
||||||
}
|
}
|
||||||
@ -225,7 +240,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.build();
|
.build();
|
||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setDisplayName("displayName")
|
.setDisplayName("displayName")
|
||||||
@ -238,13 +252,17 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setDisplayName("displayName")
|
.setDisplayName("displayName")
|
||||||
.setIconResId(R.drawable.media3_icon_circular_play)
|
.setIconResId(R.drawable.media3_icon_circular_play)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
int[] compactViewIndices =
|
int[] compactViewIndices =
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1, commandButton2),
|
ImmutableList.of(commandButton1, commandButton2),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
mockActionFactory);
|
mockActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
ArgumentCaptor<NotificationCompat.Action> actionCaptor =
|
ArgumentCaptor<NotificationCompat.Action> actionCaptor =
|
||||||
ArgumentCaptor.forClass(NotificationCompat.Action.class);
|
ArgumentCaptor.forClass(NotificationCompat.Action.class);
|
||||||
@ -254,11 +272,11 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton1);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton1);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createMediaAction(
|
.createMediaAction(
|
||||||
eq(mockMediaSession), any(), eq("displayName"), eq(commandButton2.playerCommand));
|
eq(mediaSession), any(), eq("displayName"), eq(commandButton2.playerCommand));
|
||||||
verifyNoMoreInteractions(mockActionFactory);
|
verifyNoMoreInteractions(mockActionFactory);
|
||||||
assertThat(compactViewIndices).asList().containsExactly(1);
|
assertThat(compactViewIndices).asList().containsExactly(1);
|
||||||
}
|
}
|
||||||
@ -271,25 +289,28 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.build();
|
.build();
|
||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
new CommandButton.Builder()
|
new CommandButton.Builder()
|
||||||
.setDisplayName("displayName")
|
.setDisplayName("displayName")
|
||||||
.setIconResId(R.drawable.media3_icon_circular_play)
|
.setIconResId(R.drawable.media3_icon_circular_play)
|
||||||
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
int[] compactViewIndices =
|
int[] compactViewIndices =
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1),
|
ImmutableList.of(commandButton1),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
mockActionFactory);
|
mockActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton1);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton1);
|
||||||
verifyNoMoreInteractions(mockActionFactory);
|
verifyNoMoreInteractions(mockActionFactory);
|
||||||
assertThat(compactViewIndices).asList().isEmpty();
|
assertThat(compactViewIndices).asList().isEmpty();
|
||||||
}
|
}
|
||||||
@ -301,7 +322,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.build();
|
.build();
|
||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Bundle commandButtonBundle1 = new Bundle();
|
Bundle commandButtonBundle1 = new Bundle();
|
||||||
commandButtonBundle1.putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 2);
|
commandButtonBundle1.putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 2);
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
@ -321,21 +341,25 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
||||||
.setExtras(commandButtonBundle2)
|
.setExtras(commandButtonBundle2)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
int[] compactViewIndices =
|
int[] compactViewIndices =
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1, commandButton2),
|
ImmutableList.of(commandButton1, commandButton2),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
mockActionFactory);
|
mockActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton1);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton1);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton2);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton2);
|
||||||
verifyNoMoreInteractions(mockActionFactory);
|
verifyNoMoreInteractions(mockActionFactory);
|
||||||
assertThat(compactViewIndices).asList().isEmpty();
|
assertThat(compactViewIndices).asList().isEmpty();
|
||||||
}
|
}
|
||||||
@ -347,7 +371,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.build();
|
.build();
|
||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
MediaNotification.ActionFactory mockActionFactory = mock(MediaNotification.ActionFactory.class);
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
Bundle commandButtonBundle = new Bundle();
|
Bundle commandButtonBundle = new Bundle();
|
||||||
commandButtonBundle.putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 1);
|
commandButtonBundle.putInt(DefaultMediaNotificationProvider.COMMAND_KEY_COMPACT_VIEW_INDEX, 1);
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
@ -357,18 +380,22 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
||||||
.setExtras(commandButtonBundle)
|
.setExtras(commandButtonBundle)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
int[] compactViewIndices =
|
int[] compactViewIndices =
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1),
|
ImmutableList.of(commandButton1),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
mockActionFactory);
|
mockActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
InOrder inOrder = Mockito.inOrder(mockActionFactory);
|
||||||
inOrder
|
inOrder
|
||||||
.verify(mockActionFactory)
|
.verify(mockActionFactory)
|
||||||
.createCustomActionFromCustomCommandButton(mockMediaSession, commandButton1);
|
.createCustomActionFromCustomCommandButton(mediaSession, commandButton1);
|
||||||
verifyNoMoreInteractions(mockActionFactory);
|
verifyNoMoreInteractions(mockActionFactory);
|
||||||
// [INDEX_UNSET, 1, INDEX_UNSET] cropped up to the first INDEX_UNSET value
|
// [INDEX_UNSET, 1, INDEX_UNSET] cropped up to the first INDEX_UNSET value
|
||||||
assertThat(compactViewIndices).asList().isEmpty();
|
assertThat(compactViewIndices).asList().isEmpty();
|
||||||
@ -382,10 +409,6 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
NotificationCompat.Builder mockNotificationBuilder = mock(NotificationCompat.Builder.class);
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession = mock(MediaSession.class);
|
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(Uri.parse("http://example.com"));
|
|
||||||
Bundle commandButtonBundle = new Bundle();
|
Bundle commandButtonBundle = new Bundle();
|
||||||
commandButtonBundle.putString("testKey", "testValue");
|
commandButtonBundle.putString("testKey", "testValue");
|
||||||
CommandButton commandButton1 =
|
CommandButton commandButton1 =
|
||||||
@ -395,19 +418,21 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
.setSessionCommand(new SessionCommand("action1", Bundle.EMPTY))
|
||||||
.setExtras(commandButtonBundle)
|
.setExtras(commandButtonBundle)
|
||||||
.build();
|
.build();
|
||||||
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession = new MediaSession.Builder(context, player).build();
|
||||||
|
|
||||||
defaultMediaNotificationProvider.addNotificationActions(
|
defaultMediaNotificationProvider.addNotificationActions(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(commandButton1),
|
ImmutableList.of(commandButton1),
|
||||||
mockNotificationBuilder,
|
mockNotificationBuilder,
|
||||||
defaultActionFactory);
|
defaultActionFactory);
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
ArgumentCaptor<NotificationCompat.Action> actionCaptor =
|
ArgumentCaptor<NotificationCompat.Action> actionCaptor =
|
||||||
ArgumentCaptor.forClass(NotificationCompat.Action.class);
|
ArgumentCaptor.forClass(NotificationCompat.Action.class);
|
||||||
verify(mockNotificationBuilder).addAction(actionCaptor.capture());
|
verify(mockNotificationBuilder).addAction(actionCaptor.capture());
|
||||||
verifyNoMoreInteractions(mockNotificationBuilder);
|
verifyNoMoreInteractions(mockNotificationBuilder);
|
||||||
verify(mockMediaSessionImpl).getUri();
|
|
||||||
verifyNoMoreInteractions(mockMediaSessionImpl);
|
|
||||||
List<NotificationCompat.Action> actions = actionCaptor.getAllValues();
|
List<NotificationCompat.Action> actions = actionCaptor.getAllValues();
|
||||||
assertThat(actions).hasSize(1);
|
assertThat(actions).hasSize(1);
|
||||||
assertThat(String.valueOf(actions.get(0).title)).isEqualTo("displayName1");
|
assertThat(String.valueOf(actions.get(0).title)).isEqualTo("displayName1");
|
||||||
@ -426,8 +451,8 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
shadowOf(Looper.getMainLooper()).pause();
|
shadowOf(Looper.getMainLooper()).pause();
|
||||||
// Create a MediaSession whose player returns non-null media metadata so that the
|
// Create a MediaSession whose player returns non-null media metadata so that the
|
||||||
// notification provider will request to load artwork bitmaps.
|
// notification provider will request to load artwork bitmaps.
|
||||||
MediaSession mockMediaSession =
|
Player player =
|
||||||
createMockMediaSessionForNotification(
|
createPlayerWithMetadata(
|
||||||
new MediaMetadata.Builder()
|
new MediaMetadata.Builder()
|
||||||
.setArtworkUri(Uri.parse("http://example.test/image.jpg"))
|
.setArtworkUri(Uri.parse("http://example.test/image.jpg"))
|
||||||
.build());
|
.build());
|
||||||
@ -436,7 +461,8 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
SettableFuture<Bitmap> bitmapFuture = SettableFuture.create();
|
SettableFuture<Bitmap> bitmapFuture = SettableFuture.create();
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(bitmapFuture);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(bitmapFuture);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
new DefaultMediaNotificationProvider.Builder(ApplicationProvider.getApplicationContext())
|
||||||
.build();
|
.build();
|
||||||
@ -447,7 +473,7 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
MediaNotification.Provider.Callback mockOnNotificationChangedCallback1 =
|
MediaNotification.Provider.Callback mockOnNotificationChangedCallback1 =
|
||||||
mock(MediaNotification.Provider.Callback.class);
|
mock(MediaNotification.Provider.Callback.class);
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
/* customLayout= */ ImmutableList.of(),
|
/* customLayout= */ ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mockOnNotificationChangedCallback1);
|
mockOnNotificationChangedCallback1);
|
||||||
@ -456,13 +482,16 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
MediaNotification.Provider.Callback mockOnNotificationChangedCallback2 =
|
MediaNotification.Provider.Callback mockOnNotificationChangedCallback2 =
|
||||||
mock(MediaNotification.Provider.Callback.class);
|
mock(MediaNotification.Provider.Callback.class);
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
/* customLayout= */ ImmutableList.of(),
|
/* customLayout= */ ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mockOnNotificationChangedCallback2);
|
mockOnNotificationChangedCallback2);
|
||||||
// The bitmap has arrived.
|
// The bitmap has arrived.
|
||||||
bitmapFuture.set(Bitmap.createBitmap(/* width= */ 8, /* height= */ 8, Bitmap.Config.RGB_565));
|
bitmapFuture.set(Bitmap.createBitmap(/* width= */ 8, /* height= */ 8, Bitmap.Config.RGB_565));
|
||||||
ShadowLooper.idleMainLooper();
|
ShadowLooper.idleMainLooper();
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
verify(mockOnNotificationChangedCallback2).onNotificationChanged(any());
|
verify(mockOnNotificationChangedCallback2).onNotificationChanged(any());
|
||||||
verifyNoInteractions(mockOnNotificationChangedCallback1);
|
verifyNoInteractions(mockOnNotificationChangedCallback1);
|
||||||
}
|
}
|
||||||
@ -472,19 +501,22 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(notification.notificationId).isEqualTo(DEFAULT_NOTIFICATION_ID);
|
assertThat(notification.notificationId).isEqualTo(DEFAULT_NOTIFICATION_ID);
|
||||||
assertThat(notification.notification.getChannelId()).isEqualTo(DEFAULT_CHANNEL_ID);
|
assertThat(notification.notification.getChannelId()).isEqualTo(DEFAULT_CHANNEL_ID);
|
||||||
@ -506,19 +538,22 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
.setChannelId(/* channelId= */ "customChannelId")
|
.setChannelId(/* channelId= */ "customChannelId")
|
||||||
.setChannelName(/* channelNameResourceId= */ R.string.media3_controls_play_description)
|
.setChannelName(/* channelNameResourceId= */ R.string.media3_controls_play_description)
|
||||||
.build();
|
.build();
|
||||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(notification.notificationId).isEqualTo(2);
|
assertThat(notification.notificationId).isEqualTo(2);
|
||||||
assertThat(notification.notification.getChannelId()).isEqualTo("customChannelId");
|
assertThat(notification.notification.getChannelId()).isEqualTo("customChannelId");
|
||||||
@ -543,19 +578,22 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
})
|
})
|
||||||
.setChannelName(/* channelNameResourceId= */ R.string.media3_controls_play_description)
|
.setChannelName(/* channelNameResourceId= */ R.string.media3_controls_play_description)
|
||||||
.build();
|
.build();
|
||||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(notification.notificationId).isEqualTo(3);
|
assertThat(notification.notificationId).isEqualTo(3);
|
||||||
}
|
}
|
||||||
@ -567,14 +605,15 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
@ -582,10 +621,12 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
defaultMediaNotificationProvider.setSmallIcon(R.drawable.media3_icon_circular_play);
|
defaultMediaNotificationProvider.setSmallIcon(R.drawable.media3_icon_circular_play);
|
||||||
MediaNotification notificationWithSmallIcon =
|
MediaNotification notificationWithSmallIcon =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(notification.notification.getSmallIcon().getResId())
|
assertThat(notification.notification.getSmallIcon().getResId())
|
||||||
.isEqualTo(R.drawable.media3_notification_small_icon);
|
.isEqualTo(R.drawable.media3_notification_small_icon);
|
||||||
@ -600,19 +641,20 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession =
|
Player player = createPlayerWithMetadata(new MediaMetadata.Builder().setTitle("title").build());
|
||||||
createMockMediaSessionForNotification(
|
|
||||||
new MediaMetadata.Builder().setTitle("title").build());
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
boolean isMediaMetadataTitleEqualToNotificationContentTitle =
|
boolean isMediaMetadataTitleEqualToNotificationContentTitle =
|
||||||
"title".contentEquals(NotificationCompat.getContentTitle(notification.notification));
|
"title".contentEquals(NotificationCompat.getContentTitle(notification.notification));
|
||||||
@ -626,19 +668,21 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession =
|
Player player =
|
||||||
createMockMediaSessionForNotification(
|
createPlayerWithMetadata(new MediaMetadata.Builder().setArtist("artist").build());
|
||||||
new MediaMetadata.Builder().setArtist("artist").build());
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
boolean isMediaMetadataArtistEqualToNotificationContentText =
|
boolean isMediaMetadataArtistEqualToNotificationContentText =
|
||||||
"artist".contentEquals(NotificationCompat.getContentText(notification.notification));
|
"artist".contentEquals(NotificationCompat.getContentText(notification.notification));
|
||||||
@ -653,20 +697,23 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
new DefaultMediaNotificationProvider.Builder(context).build();
|
new DefaultMediaNotificationProvider.Builder(context).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
MediaSession mockMediaSession =
|
Player player =
|
||||||
createMockMediaSessionForNotification(
|
createPlayerWithMetadata(
|
||||||
new MediaMetadata.Builder().setArtist("artist").setTitle("title").build(),
|
new MediaMetadata.Builder().setArtist("artist").setTitle("title").build(),
|
||||||
/* getMetadataCommandAvailable= */ false);
|
/* isMetadataCommandAvailable= */ false);
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
mock(MediaNotification.Provider.Callback.class));
|
mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(NotificationCompat.getContentText(notification.notification)).isNull();
|
assertThat(NotificationCompat.getContentText(notification.notification)).isNull();
|
||||||
assertThat(NotificationCompat.getContentTitle(notification.notification)).isNull();
|
assertThat(NotificationCompat.getContentTitle(notification.notification)).isNull();
|
||||||
@ -681,19 +728,22 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
Context context = ApplicationProvider.getApplicationContext();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
DefaultMediaNotificationProvider defaultMediaNotificationProvider =
|
||||||
new DefaultMediaNotificationProvider(context);
|
new DefaultMediaNotificationProvider(context);
|
||||||
MediaSession mockMediaSession = createMockMediaSessionForNotification(MediaMetadata.EMPTY);
|
|
||||||
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
BitmapLoader mockBitmapLoader = mock(BitmapLoader.class);
|
||||||
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
when(mockBitmapLoader.loadBitmapFromMetadata(any())).thenReturn(null);
|
||||||
when(mockMediaSession.getBitmapLoader()).thenReturn(mockBitmapLoader);
|
Player player = new TestExoPlayerBuilder(context).build();
|
||||||
|
MediaSession mediaSession =
|
||||||
|
new MediaSession.Builder(context, player).setBitmapLoader(mockBitmapLoader).build();
|
||||||
DefaultActionFactory defaultActionFactory =
|
DefaultActionFactory defaultActionFactory =
|
||||||
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
new DefaultActionFactory(Robolectric.setupService(TestService.class));
|
||||||
|
|
||||||
MediaNotification notification =
|
MediaNotification notification =
|
||||||
defaultMediaNotificationProvider.createNotification(
|
defaultMediaNotificationProvider.createNotification(
|
||||||
mockMediaSession,
|
mediaSession,
|
||||||
/* customLayout= */ ImmutableList.of(),
|
/* customLayout= */ ImmutableList.of(),
|
||||||
defaultActionFactory,
|
defaultActionFactory,
|
||||||
/* onNotificationChangedCallback= */ mock(MediaNotification.Provider.Callback.class));
|
/* onNotificationChangedCallback= */ mock(MediaNotification.Provider.Callback.class));
|
||||||
|
mediaSession.release();
|
||||||
|
player.release();
|
||||||
|
|
||||||
assertThat(notification.notificationId).isEqualTo(DEFAULT_NOTIFICATION_ID);
|
assertThat(notification.notificationId).isEqualTo(DEFAULT_NOTIFICATION_ID);
|
||||||
assertThat(notification.notification.getChannelId()).isEqualTo(DEFAULT_CHANNEL_ID);
|
assertThat(notification.notification.getChannelId()).isEqualTo(DEFAULT_CHANNEL_ID);
|
||||||
@ -765,29 +815,32 @@ public class DefaultMediaNotificationProviderTest {
|
|||||||
assertThat(found).isTrue();
|
assertThat(found).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaSession createMockMediaSessionForNotification(MediaMetadata mediaMetadata) {
|
private Player createPlayerWithMetadata(MediaMetadata mediaMetadata) {
|
||||||
return createMockMediaSessionForNotification(
|
return createPlayerWithMetadata(mediaMetadata, /* isMetadataCommandAvailable= */ true);
|
||||||
mediaMetadata, /* getMetadataCommandAvailable= */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MediaSession createMockMediaSessionForNotification(
|
private Player createPlayerWithMetadata(
|
||||||
MediaMetadata mediaMetadata, boolean getMetadataCommandAvailable) {
|
MediaMetadata mediaMetadata, boolean isMetadataCommandAvailable) {
|
||||||
Player mockPlayer = mock(Player.class);
|
return new ForwardingPlayer(new TestExoPlayerBuilder(context).build()) {
|
||||||
when(mockPlayer.isCommandAvailable(anyInt())).thenReturn(false);
|
@Override
|
||||||
if (getMetadataCommandAvailable) {
|
public boolean isCommandAvailable(int command) {
|
||||||
when(mockPlayer.getAvailableCommands())
|
return isMetadataCommandAvailable || command != Player.COMMAND_GET_MEDIA_ITEMS_METADATA;
|
||||||
.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);
|
@Override
|
||||||
MediaSessionImpl mockMediaSessionImpl = mock(MediaSessionImpl.class);
|
public Commands getAvailableCommands() {
|
||||||
when(mockMediaSession.getImpl()).thenReturn(mockMediaSessionImpl);
|
Commands.Builder commandsBuilder = new Commands.Builder().addAllCommands();
|
||||||
when(mockMediaSessionImpl.getUri()).thenReturn(Uri.parse("https://example.test"));
|
if (!isMetadataCommandAvailable) {
|
||||||
return mockMediaSession;
|
commandsBuilder.remove(Player.COMMAND_GET_MEDIA_ITEMS_METADATA);
|
||||||
|
}
|
||||||
|
return commandsBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaMetadata getMediaMetadata() {
|
||||||
|
return isMetadataCommandAvailable ? mediaMetadata : MediaMetadata.EMPTY;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A test service for unit tests. */
|
/** A test service for unit tests. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user