diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaLibraryService.java b/libraries/session/src/main/java/androidx/media3/session/MediaLibraryService.java index 688f23c2cc4..99616000190 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaLibraryService.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaLibraryService.java @@ -606,6 +606,24 @@ public Builder setMediaButtonPreferences(List mediaButtonPreferen return super.setMediaButtonPreferences(mediaButtonPreferences); } + /** + * Sets whether to opt into the System UI playback resumption. If this is set to {@code true}, + * {@link MediaSession.Callback#onPlaybackResumption(MediaSession, ControllerInfo, boolean)} + * must be implemented. + * + *

The default is {@code null}. + * + * @param systemUiPlaybackResumptionOptIn Whether to opt into System UI playback resumption + * notification, or {@code null} to determine based on the presence of a {@link + * MediaButtonReceiver} in the manifest. + */ + @UnstableApi + @Override + public Builder setSystemUiPlaybackResumptionOptIn( + @Nullable Boolean systemUiPlaybackResumptionOptIn) { + return super.setSystemUiPlaybackResumptionOptIn(systemUiPlaybackResumptionOptIn); + } + /** * Sets whether a play button is shown if playback is {@linkplain * Player#getPlaybackSuppressionReason() suppressed}. @@ -705,7 +723,8 @@ public MediaLibrarySession build() { checkNotNull(bitmapLoader), playIfSuppressed, isPeriodicPositionUpdateEnabled, - libraryErrorReplicationMode); + libraryErrorReplicationMode, + systemUiPlaybackResumptionOptIn); } } @@ -723,7 +742,8 @@ public MediaLibrarySession build() { BitmapLoader bitmapLoader, boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, - @LibraryErrorReplicationMode int libraryErrorReplicationMode) { + @LibraryErrorReplicationMode int libraryErrorReplicationMode, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { super( context, id, @@ -739,7 +759,8 @@ public MediaLibrarySession build() { playIfSuppressed, isPeriodicPositionUpdateEnabled, libraryErrorReplicationMode, - /* useLegacySurfaceHandling= */ false); + /* useLegacySurfaceHandling= */ false, + systemUiPlaybackResumptionOptIn); } @Override @@ -758,7 +779,8 @@ public MediaLibrarySession build() { boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, @LibraryErrorReplicationMode int libraryErrorReplicationMode, - boolean useLegacySurfaceHandling) { + boolean useLegacySurfaceHandling, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { return new MediaLibrarySessionImpl( this, context, @@ -774,7 +796,8 @@ public MediaLibrarySession build() { bitmapLoader, playIfSuppressed, isPeriodicPositionUpdateEnabled, - libraryErrorReplicationMode); + libraryErrorReplicationMode, + systemUiPlaybackResumptionOptIn); } @Override diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaLibrarySessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaLibrarySessionImpl.java index c04bf4a3ba5..05366562f00 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaLibrarySessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaLibrarySessionImpl.java @@ -81,7 +81,8 @@ public MediaLibrarySessionImpl( BitmapLoader bitmapLoader, boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, - @MediaLibrarySession.LibraryErrorReplicationMode int libraryErrorReplicationMode) { + @MediaLibrarySession.LibraryErrorReplicationMode int libraryErrorReplicationMode, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { super( instance, context, @@ -97,7 +98,8 @@ public MediaLibrarySessionImpl( bitmapLoader, playIfSuppressed, isPeriodicPositionUpdateEnabled, - /* useLegacySurfaceHandling= */ false); + /* useLegacySurfaceHandling= */ false, + systemUiPlaybackResumptionOptIn); this.instance = instance; this.callback = callback; this.libraryErrorReplicationMode = libraryErrorReplicationMode; 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 a2eece61663..1cf63f9b7d5 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSession.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSession.java @@ -463,6 +463,24 @@ public Builder setShowPlayButtonIfPlaybackIsSuppressed( return super.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfPlaybackIsSuppressed); } + /** + * Sets whether to opt into the System UI playback resumption. If this is set to {@code true}, + * {@link MediaSession.Callback#onPlaybackResumption(MediaSession, ControllerInfo, boolean)} + * must be implemented. + * + *

The default is {@code null}. + * + * @param systemUiPlaybackResumptionOptIn Whether to opt into System UI playback resumption + * notification, or {@code null} to determine based on the presence of a {@link + * MediaButtonReceiver} in the manifest. + */ + @UnstableApi + @Override + public Builder setSystemUiPlaybackResumptionOptIn( + @Nullable Boolean systemUiPlaybackResumptionOptIn) { + return super.setSystemUiPlaybackResumptionOptIn(systemUiPlaybackResumptionOptIn); + } + /** * Sets {@link CommandButton command buttons} that can be added as {@linkplain * MediaMetadata.Builder#setSupportedCommands(List) supported media item commands}. @@ -523,7 +541,8 @@ public MediaSession build() { playIfSuppressed, isPeriodicPositionUpdateEnabled, MediaLibrarySession.LIBRARY_ERROR_REPLICATION_MODE_NONE, - useLegacySurfaceHandling); + useLegacySurfaceHandling, + systemUiPlaybackResumptionOptIn); } } @@ -778,7 +797,8 @@ public static ControllerInfo createTestOnlyControllerInfo( boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, @MediaLibrarySession.LibraryErrorReplicationMode int libraryErrorReplicationMode, - boolean useLegacySurfaceHandling) { + boolean useLegacySurfaceHandling, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { synchronized (STATIC_LOCK) { if (SESSION_ID_TO_SESSION_MAP.containsKey(id)) { throw new IllegalStateException("Session ID must be unique. ID=" + id); @@ -801,7 +821,8 @@ public static ControllerInfo createTestOnlyControllerInfo( playIfSuppressed, isPeriodicPositionUpdateEnabled, libraryErrorReplicationMode, - useLegacySurfaceHandling); + useLegacySurfaceHandling, + systemUiPlaybackResumptionOptIn); } /* package */ MediaSessionImpl createImpl( @@ -819,7 +840,8 @@ public static ControllerInfo createTestOnlyControllerInfo( boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, @MediaLibrarySession.LibraryErrorReplicationMode int libraryErrorReplicationMode, - boolean useLegacySurfaceHandling) { + boolean useLegacySurfaceHandling, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { return new MediaSessionImpl( this, context, @@ -835,7 +857,8 @@ public static ControllerInfo createTestOnlyControllerInfo( bitmapLoader, playIfSuppressed, isPeriodicPositionUpdateEnabled, - useLegacySurfaceHandling); + useLegacySurfaceHandling, + systemUiPlaybackResumptionOptIn); } /* package */ MediaSessionImpl getImpl() { @@ -2487,6 +2510,7 @@ default void onError(int seq, SessionError sessionError) throws RemoteException /* package */ ImmutableList mediaButtonPreferences; /* package */ ImmutableList commandButtonsForMediaItems; /* package */ boolean isPeriodicPositionUpdateEnabled; + /* package */ @Nullable Boolean systemUiPlaybackResumptionOptIn; public BuilderBase(Context context, Player player, CallbackT callback) { this.context = checkNotNull(context); @@ -2562,6 +2586,14 @@ public BuilderT setMediaButtonPreferences(List mediaButtonPrefere return (BuilderT) this; } + @CanIgnoreReturnValue + @SuppressWarnings("unchecked") + public BuilderT setSystemUiPlaybackResumptionOptIn( + @Nullable Boolean systemUiPlaybackResumptionOptIn) { + this.systemUiPlaybackResumptionOptIn = systemUiPlaybackResumptionOptIn; + return (BuilderT) this; + } + @CanIgnoreReturnValue @SuppressWarnings("unchecked") public BuilderT setShowPlayButtonIfPlaybackIsSuppressed( diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java index 90f17afdcca..7cac6643375 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionImpl.java @@ -160,6 +160,7 @@ private ImmutableList mediaButtonPreferences; private Bundle sessionExtras; @Nullable private PlaybackException playbackException; + private final @Nullable Boolean systemUiPlaybackResumptionOptIn; @SuppressWarnings("argument.type.incompatible") // Using this in System.identityHashCode public MediaSessionImpl( @@ -177,7 +178,8 @@ public MediaSessionImpl( BitmapLoader bitmapLoader, boolean playIfSuppressed, boolean isPeriodicPositionUpdateEnabled, - boolean useLegacySurfaceHandling) { + boolean useLegacySurfaceHandling, + @Nullable Boolean systemUiPlaybackResumptionOptIn) { Log.i( TAG, "Init " @@ -200,6 +202,7 @@ public MediaSessionImpl( this.playIfSuppressed = playIfSuppressed; this.isPeriodicPositionUpdateEnabled = isPeriodicPositionUpdateEnabled; this.useLegacySurfaceHandling = useLegacySurfaceHandling; + this.systemUiPlaybackResumptionOptIn = systemUiPlaybackResumptionOptIn; @SuppressWarnings("nullness:assignment") @Initialized @@ -1092,7 +1095,9 @@ protected MediaSessionServiceLegacyStub getLegacyBrowserService() { } /* package */ boolean canResumePlaybackOnStart() { - return sessionLegacyStub.canResumePlaybackOnStart(); + return systemUiPlaybackResumptionOptIn != null + ? systemUiPlaybackResumptionOptIn + : sessionLegacyStub.canResumePlaybackOnStart(); } /* package */ void setMediaSessionListener(MediaSession.Listener listener) {