Make foreground service timeout configurable

This allows apps to set a shorter timeout if so desired.

Issue: androidx/media#2206

#cherrypick

PiperOrigin-RevId: 735360459
(cherry picked from commit 222950cfd1bdc942b90e0991e6b96a3f2c86518a)
This commit is contained in:
tonihei 2025-03-10 06:58:55 -07:00
parent 67ec5b76ad
commit b215670445
2 changed files with 40 additions and 6 deletions

View File

@ -57,7 +57,6 @@ import java.util.concurrent.TimeoutException;
private static final String TAG = "MediaNtfMng";
private static final int MSG_USER_ENGAGED_TIMEOUT = 1;
private static final long USER_ENGAGED_TIMEOUT_MS = 600_000;
private final MediaSessionService mediaSessionService;
private final MediaNotification.Provider mediaNotificationProvider;
@ -73,6 +72,7 @@ import java.util.concurrent.TimeoutException;
private boolean startedInForeground;
private boolean isUserEngaged;
private boolean isUserEngagedTimeoutEnabled;
private long userEngagedTimeoutMs;
public MediaNotificationManager(
MediaSessionService mediaSessionService,
@ -88,6 +88,7 @@ import java.util.concurrent.TimeoutException;
controllerMap = new HashMap<>();
startedInForeground = false;
isUserEngagedTimeoutEnabled = true;
userEngagedTimeoutMs = MediaSessionService.DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS;
}
public void addSession(MediaSession session) {
@ -191,6 +192,10 @@ import java.util.concurrent.TimeoutException;
return startedInForeground;
}
public void setUserEngagedTimeoutMs(long userEngagedTimeoutMs) {
this.userEngagedTimeoutMs = userEngagedTimeoutMs;
}
@Override
public boolean handleMessage(Message msg) {
if (msg.what == MSG_USER_ENGAGED_TIMEOUT) {
@ -206,8 +211,9 @@ import java.util.concurrent.TimeoutException;
/* package */ boolean shouldRunInForeground(boolean startInForegroundWhenPaused) {
boolean isUserEngaged = isAnySessionUserEngaged(startInForegroundWhenPaused);
if (this.isUserEngaged && !isUserEngaged && isUserEngagedTimeoutEnabled) {
mainHandler.sendEmptyMessageDelayed(MSG_USER_ENGAGED_TIMEOUT, USER_ENGAGED_TIMEOUT_MS);
boolean useTimeout = isUserEngagedTimeoutEnabled && userEngagedTimeoutMs > 0;
if (this.isUserEngaged && !isUserEngaged && useTimeout) {
mainHandler.sendEmptyMessageDelayed(MSG_USER_ENGAGED_TIMEOUT, userEngagedTimeoutMs);
} else if (isUserEngaged) {
mainHandler.removeMessages(MSG_USER_ENGAGED_TIMEOUT);
}

View File

@ -159,6 +159,12 @@ public abstract class MediaSessionService extends Service {
/** The action for {@link Intent} filter that must be declared by the service. */
public static final String SERVICE_INTERFACE = "androidx.media3.session.MediaSessionService";
/**
* The default timeout for a session to stay in a foreground service state after it paused,
* stopped, failed or ended.
*/
@UnstableApi public static final long DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS = 600_000;
private static final String TAG = "MSessionService";
private final Object lock;
@ -471,6 +477,27 @@ public abstract class MediaSessionService extends Service {
/* maxCommandsForMediaItems= */ 0);
}
/**
* Sets the timeout for a session to stay in a foreground service state after it paused, stopped,
* failed or ended.
*
* <p>Has no effect on already running timeouts.
*
* <p>The default and maximum value is {@link #DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS}. If a larger
* value is provided, it will be clamped down to {@link #DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS}.
*
* @param foregroundServiceTimeoutMs The timeout in milliseconds.
*/
@UnstableApi
public final void setForegroundServiceTimeoutMs(long foregroundServiceTimeoutMs) {
getMediaNotificationManager()
.setUserEngagedTimeoutMs(
Util.constrainValue(
foregroundServiceTimeoutMs,
/* min= */ 0,
/* max= */ DEFAULT_FOREGROUND_SERVICE_TIMEOUT_MS));
}
/**
* Returns whether there is a session with ongoing user-engaged playback that is run in a
* foreground service.
@ -478,9 +505,10 @@ public abstract class MediaSessionService extends Service {
* <p>It is only possible to terminate the service with {@link #stopSelf()} if this method returns
* {@code false}.
*
* <p>Note that sessions are kept in foreground and this method returns {@code true} for a period
* of 10 minutes after they paused, stopped or failed. Use {@link #pauseAllPlayersAndStopSelf()}
* to pause all ongoing playbacks immediately and terminate the service.
* <p>Note that sessions are kept in foreground and this method returns {@code true} for the
* {@linkplain #setForegroundServiceTimeoutMs foreground service timeout} after they paused,
* stopped, failed or ended. Use {@link #pauseAllPlayersAndStopSelf()} to pause all ongoing
* playbacks immediately and terminate the service.
*/
@UnstableApi
public boolean isPlaybackOngoing() {