From c403b4ce7ce9a2964ff754bb394782cc36fb882d Mon Sep 17 00:00:00 2001 From: christosts Date: Wed, 9 Nov 2022 14:58:49 +0000 Subject: [PATCH] MediaController: Add missing event flags (2/2) This is the follow-up commit where the onEvents callback raised by MediaController contains the missing events, for the case where MediaController is connected to a legacy MediaSession. #minor-release PiperOrigin-RevId: 487231996 --- .../session/MediaControllerImplLegacy.java | 12 +- ...lerListenerWithMediaSessionCompatTest.java | 166 ++++++++++++++++++ 2 files changed, 170 insertions(+), 8 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java index 3be371c530..f6c9ef440b 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -1435,9 +1435,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED)); } if (!Util.areEqual(oldLegacyPlayerInfo.queueTitle, newLegacyPlayerInfo.queueTitle)) { - // TODO(b/187152483): Set proper event code when available. listeners.queueEvent( - C.INDEX_UNSET, + Player.EVENT_PLAYLIST_METADATA_CHANGED, (listener) -> listener.onPlaylistMetadataChanged(newControllerInfo.playerInfo.playlistMetadata)); } @@ -1515,23 +1514,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; } if (!oldControllerInfo.playerInfo.audioAttributes.equals( newControllerInfo.playerInfo.audioAttributes)) { - // TODO(b/187152483): Set proper event code when available. listeners.queueEvent( - C.INDEX_UNSET, + Player.EVENT_AUDIO_ATTRIBUTES_CHANGED, (listener) -> listener.onAudioAttributesChanged(newControllerInfo.playerInfo.audioAttributes)); } if (!oldControllerInfo.playerInfo.deviceInfo.equals(newControllerInfo.playerInfo.deviceInfo)) { - // TODO(b/187152483): Set proper event code when available. listeners.queueEvent( - C.INDEX_UNSET, + Player.EVENT_DEVICE_INFO_CHANGED, (listener) -> listener.onDeviceInfoChanged(newControllerInfo.playerInfo.deviceInfo)); } if (oldControllerInfo.playerInfo.deviceVolume != newControllerInfo.playerInfo.deviceVolume || oldControllerInfo.playerInfo.deviceMuted != newControllerInfo.playerInfo.deviceMuted) { - // TODO(b/187152483): Set proper event code when available. listeners.queueEvent( - C.INDEX_UNSET, + Player.EVENT_DEVICE_VOLUME_CHANGED, (listener) -> listener.onDeviceVolumeChanged( newControllerInfo.playerInfo.deviceVolume, diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java index 2d1d840c82..299ed7f7c2 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerListenerWithMediaSessionCompatTest.java @@ -16,17 +16,25 @@ package androidx.media3.session; import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS; +import static androidx.media3.test.session.common.TestUtils.getEventsAsList; import static com.google.common.truth.Truth.assertThat; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.junit.Assume.assumeTrue; import android.content.Context; +import android.media.AudioManager; import android.os.Bundle; import android.os.RemoteException; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; +import androidx.media.VolumeProviderCompat; +import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; +import androidx.media3.common.DeviceInfo; import androidx.media3.common.FlagSet; +import androidx.media3.common.MediaMetadata; import androidx.media3.common.Player; +import androidx.media3.common.util.Util; import androidx.media3.test.session.common.CommonConstants; import androidx.media3.test.session.common.HandlerThreadTestRule; import androidx.media3.test.session.common.MainLooperTestRule; @@ -40,6 +48,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.After; import org.junit.Before; @@ -190,4 +199,161 @@ public class MediaControllerListenerWithMediaSessionCompatTest { assertThat(countDownLatch.await(1_000, MILLISECONDS)).isTrue(); assertThat(TestUtils.equals(receivedSessionExtras.get(0), sessionExtras)).isTrue(); } + + @Test + public void onPlaylistMetadataChanged() throws Exception { + MediaController controller = controllerTestRule.createController(session.getSessionToken()); + CountDownLatch latch = new CountDownLatch(2); + AtomicReference playlistMetadataParamRef = new AtomicReference<>(); + AtomicReference playlistMetadataGetterRef = new AtomicReference<>(); + AtomicReference playlistMetadataOnEventsRef = new AtomicReference<>(); + AtomicReference onEvents = new AtomicReference<>(); + Player.Listener listener = + new Player.Listener() { + @Override + public void onPlaylistMetadataChanged(MediaMetadata mediaMetadata) { + playlistMetadataParamRef.set(mediaMetadata); + playlistMetadataGetterRef.set(controller.getPlaylistMetadata()); + latch.countDown(); + } + + @Override + public void onEvents(Player player, Player.Events events) { + onEvents.set(events); + playlistMetadataOnEventsRef.set(player.getPlaylistMetadata()); + latch.countDown(); + } + }; + threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); + + session.setQueueTitle("queue-title"); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(playlistMetadataParamRef.get().title).isEqualTo("queue-title"); + assertThat(playlistMetadataGetterRef.get()).isEqualTo(playlistMetadataParamRef.get()); + assertThat(playlistMetadataOnEventsRef.get()).isEqualTo(playlistMetadataParamRef.get()); + assertThat(getEventsAsList(onEvents.get())) + .containsExactly(Player.EVENT_PLAYLIST_METADATA_CHANGED); + } + + @Test + public void onAudioAttributesChanged() throws Exception { + // We need to trigger MediaControllerCompat.Callback.onAudioInfoChanged in order to raise the + // onAudioAttributesChanged() callback. In API 21 and 22, onAudioInfoChanged is not called when + // playback is changed to local. + assumeTrue(Util.SDK_INT != 21 && Util.SDK_INT != 22); + + session.setPlaybackToRemote( + /* volumeControl= */ VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, + /* maxVolume= */ 100, + /* currentVolume= */ 50); + MediaController controller = controllerTestRule.createController(session.getSessionToken()); + CountDownLatch latch = new CountDownLatch(2); + AtomicReference audioAttributesParamRef = new AtomicReference<>(); + AtomicReference audioAttributesGetterRef = new AtomicReference<>(); + AtomicReference audioAttributesOnEventsRef = new AtomicReference<>(); + AtomicReference onEvents = new AtomicReference<>(); + Player.Listener listener = + new Player.Listener() { + @Override + public void onAudioAttributesChanged(AudioAttributes audioAttributes) { + audioAttributesParamRef.set(audioAttributes); + audioAttributesGetterRef.set(controller.getAudioAttributes()); + latch.countDown(); + } + + @Override + public void onEvents(Player player, Player.Events events) { + onEvents.set(events); + audioAttributesOnEventsRef.set(player.getAudioAttributes()); + latch.countDown(); + } + }; + threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); + + session.setPlaybackToLocal(AudioManager.STREAM_ALARM); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(audioAttributesGetterRef.get().contentType).isEqualTo(AudioManager.STREAM_ALARM); + assertThat(audioAttributesGetterRef.get()).isEqualTo(audioAttributesParamRef.get()); + assertThat(audioAttributesOnEventsRef.get()).isEqualTo(audioAttributesParamRef.get()); + assertThat(getEventsAsList(onEvents.get())).contains(Player.EVENT_AUDIO_ATTRIBUTES_CHANGED); + } + + @Test + public void onDeviceInfoChanged() throws Exception { + MediaController controller = controllerTestRule.createController(session.getSessionToken()); + CountDownLatch latch = new CountDownLatch(2); + AtomicReference deviceInfoParamRef = new AtomicReference<>(); + AtomicReference deviceInfoGetterRef = new AtomicReference<>(); + AtomicReference deviceInfoOnEventsRef = new AtomicReference<>(); + AtomicReference onEvents = new AtomicReference<>(); + Player.Listener listener = + new Player.Listener() { + @Override + public void onDeviceInfoChanged(DeviceInfo deviceInfo) { + deviceInfoParamRef.set(deviceInfo); + deviceInfoGetterRef.set(controller.getDeviceInfo()); + latch.countDown(); + } + + @Override + public void onEvents(Player player, Player.Events events) { + deviceInfoOnEventsRef.set(player.getDeviceInfo()); + onEvents.set(events); + latch.countDown(); + } + }; + threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); + + session.setPlaybackToRemote( + /* volumeControl= */ VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, + /* maxVolume= */ 100, + /* currentVolume= */ 50); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(deviceInfoParamRef.get().playbackType).isEqualTo(DeviceInfo.PLAYBACK_TYPE_REMOTE); + assertThat(deviceInfoParamRef.get().maxVolume).isEqualTo(100); + assertThat(deviceInfoGetterRef.get()).isEqualTo(deviceInfoParamRef.get()); + assertThat(deviceInfoOnEventsRef.get()).isEqualTo(deviceInfoGetterRef.get()); + assertThat(getEventsAsList(onEvents.get())).contains(Player.EVENT_DEVICE_VOLUME_CHANGED); + } + + @Test + public void onDeviceVolumeChanged() throws Exception { + MediaController controller = controllerTestRule.createController(session.getSessionToken()); + CountDownLatch latch = new CountDownLatch(2); + AtomicInteger deviceVolumeParam = new AtomicInteger(); + AtomicInteger deviceVolumeGetter = new AtomicInteger(); + AtomicInteger deviceVolumeOnEvents = new AtomicInteger(); + AtomicReference onEvents = new AtomicReference<>(); + Player.Listener listener = + new Player.Listener() { + @Override + public void onDeviceVolumeChanged(int volume, boolean muted) { + deviceVolumeParam.set(volume); + deviceVolumeGetter.set(controller.getDeviceVolume()); + latch.countDown(); + } + + @Override + public void onEvents(Player player, Player.Events events) { + deviceVolumeOnEvents.set(player.getDeviceVolume()); + onEvents.set(events); + latch.countDown(); + } + }; + threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener)); + + session.setPlaybackToRemote( + /* volumeControl= */ VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, + /* maxVolume= */ 100, + /* currentVolume= */ 50); + + assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue(); + assertThat(deviceVolumeParam.get()).isEqualTo(50); + assertThat(deviceVolumeGetter.get()).isEqualTo(50); + assertThat(deviceVolumeOnEvents.get()).isEqualTo(50); + assertThat(getEventsAsList(onEvents.get())).contains(Player.EVENT_DEVICE_VOLUME_CHANGED); + } }