diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0b4fb8b296..6775fa6643 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -43,6 +43,15 @@ * Rename `DecoderCounters#inputBufferCount` to `queuedInputBufferCount`. * Make `SimpleExoPlayer.renderers` private. Renderers can be accessed via `ExoPlayer.getRenderer`. + * Enable support for Android platform diagnostics via + `MediaMetricsManager`. ExoPlayer will forward playback events and + performance data to the platform, which helps to provide system + performance and debugging information on the device. This data may also + be collected by Google + [if sharing usage and diagnostics data is enabled](https://support.google.com/accounts/answer/6078260) + by the user of the device. Apps can opt-out of contributing to platform + diagnostics for ExoPlayer with + `ExoPlayer.Builder.setUsePlatformDiagnostics(false)`. * Android 12 compatibility: * Upgrade the Cast extension to depend on `com.google.android.gms:play-services-cast-framework:20.1.0`. Earlier diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index a7df794bbd..6db9daa4b7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -389,6 +389,7 @@ public interface ExoPlayer extends Player { /* package */ long releaseTimeoutMs; /* package */ long detachSurfaceTimeoutMs; /* package */ boolean pauseAtEndOfMediaItems; + /* package */ boolean usePlatformDiagnostics; /* package */ boolean buildCalled; /** @@ -429,6 +430,7 @@ public interface ExoPlayer extends Player { *
  • {@code releaseTimeoutMs}: {@link #DEFAULT_RELEASE_TIMEOUT_MS} *
  • {@code detachSurfaceTimeoutMs}: {@link #DEFAULT_DETACH_SURFACE_TIMEOUT_MS} *
  • {@code pauseAtEndOfMediaItems}: {@code false} + *
  • {@code usePlatformDiagnostics}: {@code true} *
  • {@link Clock}: {@link Clock#DEFAULT} * * @@ -577,6 +579,7 @@ public interface ExoPlayer extends Player { clock = Clock.DEFAULT; releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS; detachSurfaceTimeoutMs = DEFAULT_DETACH_SURFACE_TIMEOUT_MS; + usePlatformDiagnostics = true; } /** @@ -937,6 +940,27 @@ public interface ExoPlayer extends Player { return this; } + /** + * Sets whether the player reports diagnostics data to the Android platform. + * + *

    If enabled, the player will use the {@link android.media.metrics.MediaMetricsManager} to + * create a {@link android.media.metrics.PlaybackSession} and forward playback events and + * performance data to this session. This helps to provide system performance and debugging + * information for media playback on the device. This data may also be collected by Google if sharing usage and diagnostics + * data is enabled by the user of the device. + * + * @param usePlatformDiagnostics Whether the player reports diagnostics data to the Android + * platform. + * @return This builder. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + public Builder setUsePlatformDiagnostics(boolean usePlatformDiagnostics) { + checkState(!buildCalled); + this.usePlatformDiagnostics = usePlatformDiagnostics; + return this; + } + /** * Sets the {@link Clock} that will be used by the player. Should only be set for testing * purposes. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 47ec445f1c..83396d6302 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -110,6 +110,7 @@ import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.Renderer.MessageType; import com.google.android.exoplayer2.analytics.AnalyticsCollector; import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.analytics.MediaMetricsListener; import com.google.android.exoplayer2.analytics.PlayerId; import com.google.android.exoplayer2.audio.AudioAttributes; import com.google.android.exoplayer2.audio.AudioRendererEventListener; @@ -359,7 +360,11 @@ import java.util.concurrent.TimeoutException; playbackInfoUpdateHandler.post(() -> handlePlaybackInfo(playbackInfoUpdate)); playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult); analyticsCollector.setPlayer(wrappingPlayer, applicationLooper); - PlayerId playerId = Util.SDK_INT < 31 ? new PlayerId() : Api31.createPlayerId(); + PlayerId playerId = + Util.SDK_INT < 31 + ? new PlayerId() + : Api31.registerMediaMetricsListener( + applicationContext, /* player= */ this, builder.usePlatformDiagnostics); internalPlayer = new ExoPlayerImplInternal( renderers, @@ -3045,9 +3050,17 @@ import java.util.concurrent.TimeoutException; private Api31() {} @DoNotInline - public static PlayerId createPlayerId() { - // TODO: Create a MediaMetricsListener and obtain LogSessionId from it. - return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE); + public static PlayerId registerMediaMetricsListener( + Context context, ExoPlayerImpl player, boolean usePlatformDiagnostics) { + @Nullable MediaMetricsListener listener = MediaMetricsListener.create(context); + if (listener == null) { + Log.w(TAG, "MediaMetricsService unavailable."); + return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE); + } + if (usePlatformDiagnostics) { + player.addAnalyticsListener(listener); + } + return new PlayerId(listener.getLogSessionId()); } } }