Skip to content

Commit

Permalink
Don't start the service in the foreground with a pause intent
Browse files Browse the repository at this point in the history
`PlaybackStateCompat.toKeyCode(command)` was replaced by our
own implementation of `toKeyCode()`. The legacy implementation used PLAY and PAUSE, while the new implementation uses PLAY_PAUSE. This made `pause` a pending intent that attempt to start the service in the foreground, but `service.startForeground()` won't be called in `MediaNotificationManager.updateNotificationInternal` when paused.

PiperOrigin-RevId: 476895752
  • Loading branch information
marcbaechinger committed Sep 30, 2022
1 parent 16dca18 commit acd9e58
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 2 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
service is stopped from the foreground and a notification with a play
button is shown to restart playback of the last media item
([#112](https://github.com/androidx/media/issues/112)).
* Don't start a foreground service with a pending intent for pause
([#167](https://github.com/androidx/media/issues/167)).
* RTSP:
* Add H263 fragmented packet handling
([#119](https://github.com/androidx/media/pull/119)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ public PendingIntent createMediaActionPendingIntent(
intent.setData(mediaSession.getImpl().getUri());
intent.setComponent(new ComponentName(service, service.getClass()));
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
if (Util.SDK_INT >= 26 && command == COMMAND_PLAY_PAUSE) {
if (Util.SDK_INT >= 26
&& command == COMMAND_PLAY_PAUSE
&& !mediaSession.getPlayer().getPlayWhenReady()) {
return Api26.createForegroundServicePendingIntent(service, keyCode, intent);
} else {
return PendingIntent.getService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,61 @@ public class DefaultActionFactoryTest {
public void createMediaPendingIntent_intentIsMediaAction() {
DefaultActionFactory actionFactory =
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 =
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_SEEK_FORWARD);

ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(dataUri);
}

@Test
public void createMediaPendingIntent_commandPlayPauseWhenNotPlayWhenReady_isForegroundService() {
DefaultActionFactory actionFactory =
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 =
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_PLAY_PAUSE);

ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
assertThat(shadowPendingIntent.isForegroundService()).isTrue();
}

@Test
public void createMediaPendingIntent_commandPlayPauseWhenPlayWhenReady_notAForegroundService() {
DefaultActionFactory actionFactory =
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);

PendingIntent pendingIntent =
actionFactory.createMediaActionPendingIntent(mockMediaSession, Player.COMMAND_PLAY_PAUSE);

ShadowPendingIntent shadowPendingIntent = shadowOf(pendingIntent);
assertThat(actionFactory.isMediaAction(shadowPendingIntent.getSavedIntent())).isTrue();
assertThat(shadowPendingIntent.getSavedIntent().getData()).isEqualTo(dataUri);
assertThat(shadowPendingIntent.isForegroundService()).isFalse();
}

@Test
Expand Down

0 comments on commit acd9e58

Please sign in to comment.