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