diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java index b81d3217e8..6823a73687 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -34,8 +34,10 @@ import android.os.RemoteException; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; import android.view.KeyEvent; +import androidx.annotation.DoNotInline; import androidx.annotation.GuardedBy; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; import androidx.core.app.NotificationCompat; import androidx.media.MediaSessionManager.RemoteUserInfo; @@ -728,6 +730,9 @@ public class MediaSession { */ @UnstableApi public final void setSessionActivity(PendingIntent activityPendingIntent) { + if (Util.SDK_INT >= 31) { + checkArgument(Api31.isActivity(activityPendingIntent)); + } impl.setSessionActivity(activityPendingIntent); } @@ -1943,6 +1948,9 @@ public class MediaSession { @SuppressWarnings("unchecked") public BuilderT setSessionActivity(PendingIntent pendingIntent) { + if (Util.SDK_INT >= 31) { + checkArgument(Api31.isActivity(pendingIntent)); + } sessionActivity = checkNotNull(pendingIntent); return (BuilderT) this; } @@ -1998,4 +2006,12 @@ public class MediaSession { public abstract SessionT build(); } + + @RequiresApi(31) + private static final class Api31 { + @DoNotInline + public static boolean isActivity(PendingIntent pendingIntent) { + return pendingIntent.isActivity(); + } + } } diff --git a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java index 396a423687..be892ff162 100644 --- a/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java +++ b/libraries/test_session_current/src/androidTest/java/androidx/media3/session/MediaSessionTest.java @@ -26,11 +26,13 @@ import static android.view.KeyEvent.KEYCODE_MEDIA_STOP; import static androidx.media3.common.Player.STATE_IDLE; import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS; import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS; +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.Assert.assertThrows; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -64,6 +66,8 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; @@ -166,6 +170,82 @@ public class MediaSessionTest { new MediaSession.Builder(context, player).setId("").build()); } + @Test + public void builderSetSessionActivity_activityIntent_accepted() { + PendingIntent pendingIntent = + PendingIntent.getActivity( + ApplicationProvider.getApplicationContext(), + /* requestCode= */ 0, + new Intent("action"), + PendingIntent.FLAG_IMMUTABLE); + + MediaSession session = + sessionTestRule.ensureReleaseAfterTest( + new MediaSession.Builder(getApplicationContext(), new MockPlayer.Builder().build()) + .setId("sessionActivity") + .setSessionActivity(pendingIntent) + .build()); + + assertThat(session.getSessionActivity()).isEqualTo(pendingIntent); + } + + @Test + public void setSessionActivity_activityIntent_accepted() { + PendingIntent pendingIntent = + PendingIntent.getActivity( + ApplicationProvider.getApplicationContext(), + /* requestCode= */ 0, + new Intent("action"), + PendingIntent.FLAG_IMMUTABLE); + + MediaSession session = + sessionTestRule.ensureReleaseAfterTest( + new MediaSession.Builder(getApplicationContext(), new MockPlayer.Builder().build()) + .setId("sessionActivity") + .build()); + session.setSessionActivity(pendingIntent); + + assertThat(session.getSessionActivity()).isEqualTo(pendingIntent); + } + + @Test + public void builderSetSessionActivity_nonActivityIntent_throwsIllegalArgumentException() { + Assume.assumeTrue(Util.SDK_INT >= 31); + PendingIntent pendingIntent = + PendingIntent.getBroadcast( + ApplicationProvider.getApplicationContext(), + /* requestCode= */ 0, + new Intent("action"), + PendingIntent.FLAG_IMMUTABLE); + + MediaSession.Builder builder = + new MediaSession.Builder(getApplicationContext(), new MockPlayer.Builder().build()) + .setId("sessionActivity"); + + Assert.assertThrows( + IllegalArgumentException.class, () -> builder.setSessionActivity(pendingIntent)); + } + + @Test + public void setSessionActivity_nonActivityIntent_throwsIllegalArgumentException() { + Assume.assumeTrue(Util.SDK_INT >= 31); + PendingIntent pendingIntent = + PendingIntent.getBroadcast( + ApplicationProvider.getApplicationContext(), + /* requestCode= */ 0, + new Intent("action"), + PendingIntent.FLAG_IMMUTABLE); + + MediaSession session = + sessionTestRule.ensureReleaseAfterTest( + new MediaSession.Builder(getApplicationContext(), new MockPlayer.Builder().build()) + .setId("sessionActivity") + .build()); + + Assert.assertThrows( + IllegalArgumentException.class, () -> session.setSessionActivity(pendingIntent)); + } + @Test public void getPlayer() throws Exception { assertThat(handler.postAndSync(session::getPlayer)).isEqualTo(player);