@UnstableApi
class Flags


Central registry for Media3 experimental feature flags.

This class provides a mechanism to control experimental features in Media3 via global canary mode and individual flag overrides, enabling safe, gradual rollout of new library behaviors.

Canary mode

Canary mode is enabled by default. Only flags that are considered safe for production usage are included in canary mode. When canary mode is disabled, these flags are inactive.

Individual overrides

Individual flags can be explicitly enabled or disabled, regardless of the canary mode state. An explicit override always takes precedence over the canary mode default.

Threading

Flag configuration must be done on the application thread before creating any Media3 components (e.g., ExoPlayer, Transformer). Flag queries from other threads (e.g., the playback thread) rely on happens-before relationships established by start and android.os.Handler message posting during component setup.

Testing

In unit tests, androidx.media3.test.utils.Media3FlagsRule is the preferred way to manage flag states and automatically reset all flag overrides and canary mode after each test.

Summary

Nested types

@Documented
@Retention(value = RetentionPolicy.SOURCE)
@Target(value = ElementType.TYPE_USE)
@IntDef(open = true, value = )
annotation Flags.Flag

Flags for experimental features in Media3.

Constants

const Int

Flag to enable dynamic scheduling in ExoPlayer.

const Int

Flag to enable delegating end-position clipping to MediaPeriod instances in ExoPlayer.

const Int

Flag to enable passing BUFFER_FLAG_DECODE_ONLY to android.media.MediaCodec on API 34+.

const Int

Flag to enable stuck playing detection in ExoPlayer.

const Int

Flag to enable enforcing that read and peek methods in ParsableByteArray do not read beyond limit.

const Int

Flag to enable parsing DASH Alternative MPD events into Period.alternativeMpdEvents in DashManifestParser.

const Int

Flag to enable per-stream media progression in ExoPlayer.

const Int

Flag to enable calling play and pause immediately after creating an android.media.AudioTrack.

const Int

Flag to enable invoking MediaCodecRenderer.onProcessedStreamChange() on the first stream.

const Int

Flag to skip calling flush before release on API 29+.

const Int

Flag to enable calculating duration-to-progress based on next output buffer presentation time in MediaCodecVideoRenderer.

Public functions

synchronized java-static Unit

Explicitly disables a flag, overriding the canary mode default.

synchronized java-static Unit

Explicitly enables a flag, overriding the canary mode default.

java-static Array<Int>!

Returns the flag identifiers that are explicitly disabled via disableFlag, overriding the canary mode default.

java-static Array<Int>!

Returns the flag identifiers that are explicitly enabled via enableFlag, overriding the canary mode default.

java-static String!

Returns a log string describing the current canary mode and flag override state.

java-static Boolean

Returns whether canary mode is currently enabled.

java-static Boolean

Checks if a specific flag is enabled.

synchronized java-static Unit

Resets the flag registry to its default configuration (all overrides cleared, canary mode enabled).

synchronized java-static Unit

Sets whether canary mode is enabled globally.

Constants

FLAG_DYNAMIC_SCHEDULING

@ExperimentalApi
const val FLAG_DYNAMIC_SCHEDULING = 3: Int

Flag to enable dynamic scheduling in ExoPlayer.

When enabled, ExoPlayer uses dynamic scheduling for its playback loop.

This flag is statically enabled and defaults to true.

FLAG_ENABLE_CLIPPING_IN_MEDIA_PERIOD

@ExperimentalApi
const val FLAG_ENABLE_CLIPPING_IN_MEDIA_PERIOD = 5: Int

Flag to enable delegating end-position clipping to MediaPeriod instances in ExoPlayer.

When enabled, clipping of the end position is delegated to the wrapped MediaPeriod rather than being handled at the media source level.

This flag is not yet covered by canary mode and defaults to false.

FLAG_ENABLE_MEDIACODEC_BUFFER_DECODE_ONLY

@ExperimentalApi
const val FLAG_ENABLE_MEDIACODEC_BUFFER_DECODE_ONLY = 6: Int

Flag to enable passing BUFFER_FLAG_DECODE_ONLY to android.media.MediaCodec on API 34+.

When enabled on API 34+, buffers before the start time in non-tunneling mode are queued with BUFFER_FLAG_DECODE_ONLY rather than being dropped after decoding.

This flag is not yet covered by canary mode and defaults to false.

FLAG_ENABLE_STUCK_PLAYING_DETECTION

@ExperimentalApi
const val FLAG_ENABLE_STUCK_PLAYING_DETECTION = 4: Int

Flag to enable stuck playing detection in ExoPlayer.

When enabled, ExoPlayer detects when playback is stuck without making progress or without ending, and triggers a playback error.

FLAG_ENFORCE_PARSABLE_BYTE_ARRAY_LIMIT

@ExperimentalApi
const val FLAG_ENFORCE_PARSABLE_BYTE_ARRAY_LIMIT = 8: Int

Flag to enable enforcing that read and peek methods in ParsableByteArray do not read beyond limit.

When enabled, reading or peeking beyond the limit throws an IndexOutOfBoundsException (or java.nio.BufferOverflowException) even if the read is within the bounds of the underlying byte array.

FLAG_PARSE_DASH_ALTERNATIVE_MPD_EVENTS

@ExperimentalApi
const val FLAG_PARSE_DASH_ALTERNATIVE_MPD_EVENTS = 11: Int

Flag to enable parsing DASH Alternative MPD events into Period.alternativeMpdEvents in DashManifestParser.

When enabled, DashManifestParser parses Alternative MPD EventStreams into both Period.eventStreams and Period.alternativeMpdEvents. When disabled, only Period.eventStreams is populated using standard EventStream parsing.

FLAG_PER_STREAM_MEDIA_PROGRESSION

@ExperimentalApi
const val FLAG_PER_STREAM_MEDIA_PROGRESSION = 1: Int

Flag to enable per-stream media progression in ExoPlayer.

When enabled, ExoPlayer may advance processing on a per-stream basis, potentially starting to process the next item in the playlist before finishing the current one. This can reduce startup latency between media items.

This flag is not yet covered by canary mode and defaults to false.

FLAG_PLAY_PAUSE_AUDIO_TRACK_ON_INIT

@ExperimentalApi
const val FLAG_PLAY_PAUSE_AUDIO_TRACK_ON_INIT = 10: Int

Flag to enable calling play and pause immediately after creating an android.media.AudioTrack.

When enabled, calling play() and pause() at initialization time triggers internal android.media.AudioTrack initialization to reduce startup latency on the first actual playback.

This flag is not yet covered by canary mode and defaults to false.

FLAG_PROCESSED_STREAM_CHANGED_AT_START

@ExperimentalApi
const val FLAG_PROCESSED_STREAM_CHANGED_AT_START = 2: Int

Flag to enable invoking MediaCodecRenderer.onProcessedStreamChange() on the first stream.

When enabled, onProcessedStreamChange() is invoked starting from the first stream. When disabled (the default), it is invoked from the second stream onwards.

This flag is not yet covered by canary mode and defaults to false.

FLAG_SKIP_AUDIO_TRACK_FLUSH_BEFORE_RELEASE

@ExperimentalApi
const val FLAG_SKIP_AUDIO_TRACK_FLUSH_BEFORE_RELEASE = 9: Int

Flag to skip calling flush before release on API 29+.

When enabled on API 29+, AudioTrackAudioOutput releases the underlying android.media.AudioTrack without calling flush() first.

FLAG_VIDEO_RENDERER_DURATION_TO_PROGRESS

@ExperimentalApi
const val FLAG_VIDEO_RENDERER_DURATION_TO_PROGRESS = 7: Int

Flag to enable calculating duration-to-progress based on next output buffer presentation time in MediaCodecVideoRenderer.

When enabled along with FLAG_DYNAMIC_SCHEDULING, MediaCodecVideoRenderer returns duration-to-progress aligned with when its next output buffer can be rendered when in asynchronous mode.

This flag is not yet covered by canary mode and defaults to false.

Public functions

disableFlag

synchronized java-static fun disableFlag(@Flags.Flag flag: Int): Unit

Explicitly disables a flag, overriding the canary mode default.

This must be called before creating any Media3 components.

Parameters
@Flags.Flag flag: Int

The flag identifier.

enableFlag

synchronized java-static fun enableFlag(@Flags.Flag flag: Int): Unit

Explicitly enables a flag, overriding the canary mode default.

This must be called before creating any Media3 components.

Parameters
@Flags.Flag flag: Int

The flag identifier.

getDisabledOverrides

@Flags.Flag
java-static fun getDisabledOverrides(): Array<Int>!

Returns the flag identifiers that are explicitly disabled via disableFlag, overriding the canary mode default.

getEnabledOverrides

@Flags.Flag
java-static fun getEnabledOverrides(): Array<Int>!

Returns the flag identifiers that are explicitly enabled via enableFlag, overriding the canary mode default.

getLogString

java-static fun getLogString(): String!

Returns a log string describing the current canary mode and flag override state.

The format is [Canary:<state>, Overrides: enabled=[<ids>], disabled=[<ids>]], or [Canary:<state>] if there are no overrides. Only deviations from the default state are listed.

isCanaryModeEnabled

java-static fun isCanaryModeEnabled(): Boolean

Returns whether canary mode is currently enabled.

isEnabled

java-static fun isEnabled(@Flags.Flag flag: Int): Boolean

Checks if a specific flag is enabled.

The resolution order is:

  1. If the flag has an explicit override (via enableFlag or disableFlag), the override value is returned.
  2. If the flag has a static value not part of canary mode, that static value is returned.
  3. Otherwise, the flag is enabled if canary mode is enabled.
Parameters
@Flags.Flag flag: Int

The flag identifier.

Returns
Boolean

Whether the flag is enabled.

resetForTesting

@VisibleForTesting
synchronized java-static fun resetForTesting(): Unit

Resets the flag registry to its default configuration (all overrides cleared, canary mode enabled).

This is intended for use in tests only to avoid test pollution. In unit tests, androidx.media3.test.utils.Media3FlagsRule is the preferred alternative to calling this method directly.

setCanaryModeEnabled

synchronized java-static fun setCanaryModeEnabled(enabled: Boolean): Unit

Sets whether canary mode is enabled globally.

Canary mode is enabled by default.

When enabled, all flags that are not statically excluded are active by default. Individual overrides set via enableFlag or disableFlag take precedence.

This must be called before creating any Media3 components.

Parameters
enabled: Boolean

Whether to enable canary mode.