From 1b3658e357adad6f12fd7cc864f0b0d64f38fb3c Mon Sep 17 00:00:00 2001 From: bachinger Date: Wed, 9 Apr 2025 07:45:44 -0700 Subject: [PATCH] Adjust AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS and make it configurable PiperOrigin-RevId: 745585764 --- RELEASENOTES.md | 3 ++ .../androidx/media3/session/MediaBrowser.java | 41 ++++++++++++++-- .../session/MediaBrowserImplLegacy.java | 12 ++++- .../media3/session/MediaController.java | 49 +++++++++++++++++-- .../session/MediaControllerImplLegacy.java | 9 ++-- 5 files changed, 98 insertions(+), 16 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3cc6cdc9a5..2ca50dc02b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -63,6 +63,9 @@ instead of `MediaCodec.BufferInfo`. * IMA extension: * Session: + * Lower aggregation timeout for platform `MediaSession` callbacks from 500 + to 100 milliseconds and add an experimental setter to allow apps to + configure this value. * UI: * Enable `PlayerSurface` to work with `ExoPlayer.setVideoEffects` and `CompositionPlayer`. diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaBrowser.java b/libraries/session/src/main/java/androidx/media3/session/MediaBrowser.java index cd3dc7edec..a857fe29f8 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaBrowser.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaBrowser.java @@ -61,6 +61,7 @@ public final class MediaBrowser extends MediaController { private Looper applicationLooper; private @MonotonicNonNull BitmapLoader bitmapLoader; private int maxCommandsForMediaItems; + private long platformSessionCallbackAggregationTimeoutMs; /** * Creates a builder for {@link MediaBrowser}. @@ -78,6 +79,8 @@ public final class MediaBrowser extends MediaController { connectionHints = Bundle.EMPTY; listener = new Listener() {}; applicationLooper = Util.getCurrentOrMainLooper(); + platformSessionCallbackAggregationTimeoutMs = + DEFAULT_PLATFORM_CALLBACK_AGGREGATION_TIMEOUT_MS; } /** @@ -156,6 +159,24 @@ public final class MediaBrowser extends MediaController { return this; } + /** + * Sets the timeout after which updates from the platform session callbacks are applied to the + * browser, in milliseconds. + * + *

The default is 100ms. + * + * @param platformSessionCallbackAggregationTimeoutMs The timeout, in milliseconds. + * @return The builder to allow chaining. + */ + @UnstableApi + @CanIgnoreReturnValue + public Builder experimentalSetPlatformSessionCallbackAggregationTimeoutMs( + long platformSessionCallbackAggregationTimeoutMs) { + this.platformSessionCallbackAggregationTimeoutMs = + platformSessionCallbackAggregationTimeoutMs; + return this; + } + /** * Builds a {@link MediaBrowser} asynchronously. * @@ -196,7 +217,8 @@ public final class MediaBrowser extends MediaController { applicationLooper, holder, bitmapLoader, - maxCommandsForMediaItems); + maxCommandsForMediaItems, + platformSessionCallbackAggregationTimeoutMs); postOrRun(new Handler(applicationLooper), () -> holder.setController(browser)); return holder; } @@ -266,7 +288,8 @@ public final class MediaBrowser extends MediaController { Looper applicationLooper, ConnectionCallback connectionCallback, @Nullable BitmapLoader bitmapLoader, - int maxCommandsForMediaItems) { + int maxCommandsForMediaItems, + long platformSessionCallbackAggregationTimeoutMs) { super( context, token, @@ -275,7 +298,8 @@ public final class MediaBrowser extends MediaController { applicationLooper, connectionCallback, bitmapLoader, - maxCommandsForMediaItems); + maxCommandsForMediaItems, + platformSessionCallbackAggregationTimeoutMs); } @Override @@ -286,12 +310,19 @@ public final class MediaBrowser extends MediaController { SessionToken token, Bundle connectionHints, Looper applicationLooper, - @Nullable BitmapLoader bitmapLoader) { + @Nullable BitmapLoader bitmapLoader, + long platformSessionCallbackAggregationTimeoutMs) { MediaBrowserImpl impl; if (token.isLegacySession()) { impl = new MediaBrowserImplLegacy( - context, this, token, connectionHints, applicationLooper, checkNotNull(bitmapLoader)); + context, + this, + token, + connectionHints, + applicationLooper, + checkNotNull(bitmapLoader), + platformSessionCallbackAggregationTimeoutMs); } else { impl = new MediaBrowserImplBase(context, this, token, connectionHints, applicationLooper); } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaBrowserImplLegacy.java b/libraries/session/src/main/java/androidx/media3/session/MediaBrowserImplLegacy.java index 9b8c7731c0..0cac58bc25 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaBrowserImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaBrowserImplLegacy.java @@ -64,8 +64,16 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; SessionToken token, Bundle connectionHints, Looper applicationLooper, - BitmapLoader bitmapLoader) { - super(context, instance, token, connectionHints, applicationLooper, bitmapLoader); + BitmapLoader bitmapLoader, + long platformSessionCallbackAggregationTimeoutMs) { + super( + context, + instance, + token, + connectionHints, + applicationLooper, + bitmapLoader, + platformSessionCallbackAggregationTimeoutMs); this.instance = instance; commandButtonsForMediaItems = ImmutableMap.of(); } diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaController.java b/libraries/session/src/main/java/androidx/media3/session/MediaController.java index 8826cbfbd8..c4a9227bba 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaController.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaController.java @@ -201,6 +201,8 @@ public class MediaController implements Player { "MediaController method is called from a wrong thread." + " See javadoc of MediaController for details."; + @UnstableApi protected static final long DEFAULT_PLATFORM_CALLBACK_AGGREGATION_TIMEOUT_MS = 100L; + /** A builder for {@link MediaController}. */ public static final class Builder { @@ -211,6 +213,7 @@ public class MediaController implements Player { private Looper applicationLooper; private @MonotonicNonNull BitmapLoader bitmapLoader; private int maxCommandsForMediaItems; + private long platformSessionCallbackAggregationTimeoutMs; /** * Creates a builder for {@link MediaController}. @@ -242,6 +245,8 @@ public class MediaController implements Player { connectionHints = Bundle.EMPTY; listener = new Listener() {}; applicationLooper = Util.getCurrentOrMainLooper(); + platformSessionCallbackAggregationTimeoutMs = + DEFAULT_PLATFORM_CALLBACK_AGGREGATION_TIMEOUT_MS; } /** @@ -320,6 +325,24 @@ public class MediaController implements Player { return this; } + /** + * Sets the timeout after which updates from the platform session callbacks are applied to the + * browser, in milliseconds. + * + *

The default is 100ms. + * + * @param platformSessionCallbackAggregationTimeoutMs The timeout, in milliseconds. + * @return tThe builder to allow chaining. + */ + @UnstableApi + @CanIgnoreReturnValue + public Builder experimentalSetPlatformSessionCallbackAggregationTimeoutMs( + long platformSessionCallbackAggregationTimeoutMs) { + this.platformSessionCallbackAggregationTimeoutMs = + platformSessionCallbackAggregationTimeoutMs; + return this; + } + /** * Builds a {@link MediaController} asynchronously. * @@ -361,7 +384,8 @@ public class MediaController implements Player { applicationLooper, holder, bitmapLoader, - maxCommandsForMediaItems); + maxCommandsForMediaItems, + platformSessionCallbackAggregationTimeoutMs); postOrRun(new Handler(applicationLooper), () -> holder.setController(controller)); return holder; } @@ -553,7 +577,8 @@ public class MediaController implements Player { Looper applicationLooper, ConnectionCallback connectionCallback, @Nullable BitmapLoader bitmapLoader, - int maxCommandsForMediaItems) { + int maxCommandsForMediaItems, + long platformSessionCallbackAggregationTimeoutMs) { checkNotNull(context, "context must not be null"); checkNotNull(token, "token must not be null"); Log.i( @@ -576,7 +601,14 @@ public class MediaController implements Player { this.connectionCallback = connectionCallback; this.maxCommandsForMediaItems = maxCommandsForMediaItems; - impl = createImpl(context, token, connectionHints, applicationLooper, bitmapLoader); + impl = + createImpl( + context, + token, + connectionHints, + applicationLooper, + bitmapLoader, + platformSessionCallbackAggregationTimeoutMs); impl.connect(); } @@ -587,10 +619,17 @@ public class MediaController implements Player { SessionToken token, Bundle connectionHints, Looper applicationLooper, - @Nullable BitmapLoader bitmapLoader) { + @Nullable BitmapLoader bitmapLoader, + long platformSessionCallbackAggregationTimeoutMs) { if (token.isLegacySession()) { return new MediaControllerImplLegacy( - context, this, token, connectionHints, applicationLooper, checkNotNull(bitmapLoader)); + context, + this, + token, + connectionHints, + applicationLooper, + checkNotNull(bitmapLoader), + platformSessionCallbackAggregationTimeoutMs); } else { return new MediaControllerImplBase(context, this, token, connectionHints, applicationLooper); } 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 13196b3869..248324f774 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaControllerImplLegacy.java @@ -93,8 +93,6 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; private static final String TAG = "MCImplLegacy"; - private static final long AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS = 500L; - /* package */ final Context context; private final MediaController instance; @@ -104,6 +102,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; private final BitmapLoader bitmapLoader; private final ImmutableList commandButtonsForMediaItems; private final Bundle connectionHints; + private final long platformSessionCallbackAggregationTimeoutMs; @Nullable private MediaControllerCompat controllerCompat; @Nullable private MediaBrowserCompat browserCompat; @@ -122,7 +121,8 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; SessionToken token, Bundle connectionHints, Looper applicationLooper, - BitmapLoader bitmapLoader) { + BitmapLoader bitmapLoader, + long platformSessionCallbackAggregationTimeoutMs) { // Initialize default values. legacyPlayerInfo = new LegacyPlayerInfo(); pendingLegacyPlayerInfo = new LegacyPlayerInfo(); @@ -140,6 +140,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; this.token = token; this.connectionHints = connectionHints; this.bitmapLoader = bitmapLoader; + this.platformSessionCallbackAggregationTimeoutMs = platformSessionCallbackAggregationTimeoutMs; currentPositionMs = C.TIME_UNSET; lastSetPlayWhenReadyCalledTimeMs = C.TIME_UNSET; // Always empty. Only supported for a MediaBrowser connected to a MediaBrowserServiceCompat. @@ -1992,7 +1993,7 @@ import org.checkerframework.checker.initialization.qual.UnderInitialization; return; } pendingChangesHandler.sendEmptyMessageDelayed( - MSG_HANDLE_PENDING_UPDATES, AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS); + MSG_HANDLE_PENDING_UPDATES, platformSessionCallbackAggregationTimeoutMs); } }