diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithFrameworkMediaSessionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithFrameworkMediaSessionTest.java index 6fe9bd8957..4bc559a762 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithFrameworkMediaSessionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaControllerWithFrameworkMediaSessionTest.java @@ -24,7 +24,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import android.content.Context; import android.media.session.MediaSession; import android.media.session.PlaybackState; -import android.os.Build; import android.os.HandlerThread; import androidx.media3.common.Player; import androidx.media3.common.Player.State; @@ -34,11 +33,11 @@ import androidx.media3.test.session.common.TestHandler; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.filters.SdkSuppress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; @@ -47,7 +46,6 @@ import org.junit.runner.RunWith; /** Tests for {@link MediaController} with framework MediaSession, which exists since Android-L. */ @RunWith(AndroidJUnit4.class) @LargeTest -@SdkSuppress(minSdkVersion = Build.VERSION_CODES.LOLLIPOP) // For framework MediaSession public class MediaControllerWithFrameworkMediaSessionTest { private static final String TAG = "MCFMediaSessionTest"; @@ -56,30 +54,22 @@ public class MediaControllerWithFrameworkMediaSessionTest { private Context context; private TestHandler handler; - private MediaSession fwkSession; @Before public void setUp() { + if (Util.SDK_INT < 21) { + return; + } context = ApplicationProvider.getApplicationContext(); HandlerThread handlerThread = new HandlerThread(TAG); handlerThread.start(); TestHandler handler = new TestHandler(handlerThread.getLooper()); this.handler = handler; - - fwkSession = new android.media.session.MediaSession(context, TAG); - fwkSession.setActive(true); - fwkSession.setFlags( - MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); - fwkSession.setCallback(new android.media.session.MediaSession.Callback() {}, handler); } @After public void cleanUp() { - if (fwkSession != null) { - fwkSession.release(); - fwkSession = null; - } if (handler != null) { if (Util.SDK_INT >= 18) { handler.getLooper().quitSafely(); @@ -90,8 +80,15 @@ public class MediaControllerWithFrameworkMediaSessionTest { } } + @SuppressWarnings("UnnecessarilyFullyQualified") // Intentionally fully qualified for fwk session. @Test public void createController() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // For framework MediaSession. + MediaSession fwkSession = new android.media.session.MediaSession(context, TAG); + fwkSession.setActive(true); + fwkSession.setFlags( + MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); + fwkSession.setCallback(new android.media.session.MediaSession.Callback() {}, handler); SessionToken token = SessionToken.createSessionToken(context, fwkSession.getSessionToken()) .get(TIMEOUT_MS, MILLISECONDS); @@ -101,10 +98,18 @@ public class MediaControllerWithFrameworkMediaSessionTest { .buildAsync() .get(SERVICE_CONNECTION_TIMEOUT_MS, MILLISECONDS); handler.postAndSync(controller::release); + fwkSession.release(); } + @SuppressWarnings("UnnecessarilyFullyQualified") // Intentionally fully qualified for fwk session. @Test public void onPlaybackStateChanged_isNotifiedByFwkSessionChanges() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // For framework MediaSession. + MediaSession fwkSession = new android.media.session.MediaSession(context, TAG); + fwkSession.setActive(true); + fwkSession.setFlags( + MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); + fwkSession.setCallback(new android.media.session.MediaSession.Callback() {}, handler); CountDownLatch playbackStateChangedLatch = new CountDownLatch(1); AtomicInteger playbackStateRef = new AtomicInteger(); AtomicBoolean playWhenReadyRef = new AtomicBoolean(); @@ -136,6 +141,7 @@ public class MediaControllerWithFrameworkMediaSessionTest { assertThat(playWhenReadyRef.get()).isTrue(); } finally { handler.postAndSync(controller::release); + fwkSession.release(); } } } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionKeyEventTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionKeyEventTest.java index a4733f6449..4caefe792e 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionKeyEventTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionKeyEventTest.java @@ -37,9 +37,9 @@ import androidx.media3.test.session.common.TestHandler; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; -import androidx.test.filters.SdkSuppress; import java.util.concurrent.CountDownLatch; import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -50,8 +50,6 @@ import org.junit.runner.RunWith; * Tests for key event handling of {@link MediaSession}. In order to get the media key events, the * player state is set to 'Playing' before every test method. */ -// TODO(b/199064299): Down minSdk to 19 (AudioManager#dispatchMediaKeyEvent() requires API 19) -@SdkSuppress(minSdkVersion = 21) @RunWith(AndroidJUnit4.class) @LargeTest public class MediaSessionKeyEventTest { @@ -88,6 +86,9 @@ public class MediaSessionKeyEventTest { @Before public void setUp() throws Exception { + if (Util.SDK_INT < 21) { + return; + } Context context = ApplicationProvider.getApplicationContext(); audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); handler = threadTestRule.getHandler(); @@ -128,6 +129,9 @@ public class MediaSessionKeyEventTest { @After public void tearDown() throws Exception { + if (Util.SDK_INT < 21) { + return; + } handler.postAndSync( () -> { if (mediaPlayer != null) { @@ -140,6 +144,7 @@ public class MediaSessionKeyEventTest { @Test public void playKeyEvent() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY, false); player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS); @@ -147,6 +152,7 @@ public class MediaSessionKeyEventTest { @Test public void pauseKeyEvent() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PAUSE, false); player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS); @@ -154,6 +160,7 @@ public class MediaSessionKeyEventTest { @Test public void nextKeyEvent() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT, false); player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS); @@ -161,6 +168,7 @@ public class MediaSessionKeyEventTest { @Test public void previousKeyEvent() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS, false); player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS); @@ -168,6 +176,7 @@ public class MediaSessionKeyEventTest { @Test public void stopKeyEvent() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_STOP, false); player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS); @@ -226,6 +235,7 @@ public class MediaSessionKeyEventTest { @Test public void playPauseKeyEvent_playing_pause() throws Exception { + Assume.assumeTrue(Util.SDK_INT >= 21); // TODO: b/199064299 - Lower minSdk to 19. handler.postAndSync( () -> { player.playWhenReady = true; diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceNotificationTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceNotificationTest.java deleted file mode 100644 index 850cf31860..0000000000 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionServiceNotificationTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.session; - -import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME; - -import android.content.ComponentName; -import android.content.Context; -import androidx.media3.common.MediaMetadata; -import androidx.media3.common.util.Util; -import androidx.media3.session.MediaLibraryService.MediaLibrarySession; -import androidx.media3.session.MediaSession.ControllerInfo; -import androidx.media3.test.session.common.HandlerThreadTestRule; -import androidx.media3.test.session.common.MainLooperTestRule; -import androidx.media3.test.session.common.R; -import androidx.media3.test.session.common.TestHandler; -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; -import java.io.IOException; -import java.io.InputStream; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Manual test of {@link MediaSessionService} for showing/removing notification when the playback is - * started/ended. - * - *
This test is a manual test, which means the one who runs this test should keep looking at the - * device and check whether the notification is shown/removed. - */ -@RunWith(AndroidJUnit4.class) -@LargeTest -public class MediaSessionServiceNotificationTest { - - private static final long NOTIFICATION_SHOW_TIME_MS = 15_000; - - @ClassRule public static MainLooperTestRule mainLooperTestRule = new MainLooperTestRule(); - - @Rule - public final HandlerThreadTestRule threadTestRule = - new HandlerThreadTestRule("MediaSessionServiceNotificationTest"); - - @Rule public final RemoteControllerTestRule controllerTestRule = new RemoteControllerTestRule(); - - private Context context; - private MockPlayer player; - - @Before - public void setUp() throws Exception { - context = ApplicationProvider.getApplicationContext(); - - MediaLibrarySession.Callback sessionCallback = - new MediaLibrarySession.Callback() { - @Override - public MediaSession.ConnectionResult onConnect( - MediaSession session, ControllerInfo controller) { - if (player == null) { - player = - new MockPlayer.Builder().setChangePlayerStateWithTransportControl(true).build(); - session.setPlayer(player); - } - if (SUPPORT_APP_PACKAGE_NAME.equals(controller.getPackageName())) { - return MediaLibrarySession.Callback.super.onConnect(session, controller); - } else { - return MediaSession.ConnectionResult.reject(); - } - } - }; - TestServiceRegistry.getInstance().setSessionCallback(sessionCallback); - - controllerTestRule.createRemoteController( - new SessionToken(context, new ComponentName(context, LocalMockMediaSessionService.class)), - /* waitForConnection= */ true, - /* connectionHints= */ null); - } - - @Test - @Ignore("Comment out this line and manually run the test.") - public void notification() throws Exception { - TestHandler handler = new TestHandler(player.getApplicationLooper()); - handler.postAndSync( - () -> { - player.mediaMetadata = createTestMediaMetadata(); - player.notifyMediaMetadataChanged(); - }); - // Notification should be shown. - // Clicking play/pause button will change the player state. - // When playing, the notification will not be removed by swiping horizontally. - // When paused, the notification can be swiped away. - Thread.sleep(NOTIFICATION_SHOW_TIME_MS); - } - - @Test - @Ignore("Comment out this line and manually run the test.") - public void notificationUpdatedWhenMediaMetadataChanged() throws Exception { - TestHandler handler = new TestHandler(player.getApplicationLooper()); - handler.postAndSync( - () -> { - player.mediaMetadata = createTestMediaMetadata(); - player.notifyMediaMetadataChanged(); - }); - // At this point, the notification should be shown. - Thread.sleep(NOTIFICATION_SHOW_TIME_MS); - // Update media metadata. - handler.postAndSync( - () -> { - player.mediaMetadata = createAnotherTestMediaMetadata(); - player.notifyMediaMetadataChanged(); - }); - // Notification should be updated. - Thread.sleep(NOTIFICATION_SHOW_TIME_MS); - } - - private MediaMetadata createTestMediaMetadata() throws IOException { - byte[] artworkData; - try (InputStream stream = context.getResources().openRawResource(R.drawable.big_buck_bunny)) { - artworkData = Util.toByteArray(stream); - } - return new MediaMetadata.Builder() - .setTitle("Test Song Name") - .setArtist("Test Artist Name") - .setArtworkData(artworkData) - .setIsPlayable(true) - .build(); - } - - private MediaMetadata createAnotherTestMediaMetadata() { - return new MediaMetadata.Builder() - .setTitle("New Song Name") - .setArtist("New Artist Name") - .setIsPlayable(true) - .build(); - } -}