diff --git a/ads/api/index.mdx b/ads/api/index.mdx index 56d7e99a6a6e..7a6f02808196 100644 --- a/ads/api/index.mdx +++ b/ads/api/index.mdx @@ -38,6 +38,7 @@ The [OptiView Ads SDK](../player-integration/optiview-ads-sdk/index.mdx) ships a The OptiView Ads SDK is in beta. Its API can still change before the first stable release, and the reference is regenerated with every SDK release. ::: -- [Web API reference](pathname:///ads/v2/api-reference/web/) for the `@dolby-optiview/ads-sdk` package. - -References for the Android, iOS, and React Native SDKs will follow. +- [Web API reference](pathname:///ads/v2/api-reference/web/) for the `@dolby-optiview/ads-sdk` package and its player adapters. +- [Android API reference](pathname:///ads/v2/api-reference/android/) for the `com.dolby.optiview:ads-sdk` artifacts (Kotlin). +- [iOS and tvOS API reference](pathname:///ads/v2/api-reference/ios/) for the `OptiViewAdsSDK` Swift packages (DocC, one module per package). +- [React Native API reference](pathname:///ads/v2/api-reference/react-native/) for the `@dolby-optiview/ads-sdk-react-native` package. diff --git a/ads/player-integration/optiview-ads-sdk/android.mdx b/ads/player-integration/optiview-ads-sdk/android.mdx index e788b0a92a91..ccc145e025fb 100644 --- a/ads/player-integration/optiview-ads-sdk/android.mdx +++ b/ads/player-integration/optiview-ads-sdk/android.mdx @@ -52,4 +52,4 @@ The `ExoPlayerAdapter` wraps a Media3 `ExoPlayer` instance. Ads are rendered in ### Custom players -Any other player can be integrated by implementing the SDK's `PlayerAdapter` interface, which exposes playback position, timing information, and basic playback controls. Contact us for the adapter interface reference. +Any other player can be integrated by implementing the SDK's [`PlayerAdapter`](pathname:///ads/v2/api-reference/android/ads-sdk-core/com.dolby.optiview.ads.core/-player-adapter/index.html) interface, which exposes playback position, timing information, and basic playback controls. diff --git a/ads/player-integration/optiview-ads-sdk/ios.mdx b/ads/player-integration/optiview-ads-sdk/ios.mdx index 14100bf1f05f..c45ea3032c30 100644 --- a/ads/player-integration/optiview-ads-sdk/ios.mdx +++ b/ads/player-integration/optiview-ads-sdk/ios.mdx @@ -52,4 +52,4 @@ The `AVPlayerAdapter` wraps an `AVPlayer` instance. Ads are rendered in an overl ### Custom players -Any other player can be integrated by implementing the SDK's `PlayerAdapter` interface, which exposes playback position, timing information, and basic playback controls. Contact us for the adapter interface reference. +Any other player can be integrated by implementing the SDK's [`PlayerAdapter`](pathname:///ads/v2/api-reference/ios/OptiViewAdsCore/documentation/optiviewadscore/playeradapter/) protocol, which exposes playback position, timing information, and basic playback controls. diff --git a/ads/static/ads/v2/api-reference/android/ads-sdk-adapter-test-kit/com.dolby.optiview.ads.testkit/-player-adapter-conformance-test/-player-adapter-conformance-test.html b/ads/static/ads/v2/api-reference/android/ads-sdk-adapter-test-kit/com.dolby.optiview.ads.testkit/-player-adapter-conformance-test/-player-adapter-conformance-test.html new file mode 100644 index 000000000000..4bcb5990ec72 --- /dev/null +++ b/ads/static/ads/v2/api-reference/android/ads-sdk-adapter-test-kit/com.dolby.optiview.ads.testkit/-player-adapter-conformance-test/-player-adapter-conformance-test.html @@ -0,0 +1,117 @@ + + +
+ +Create a fresh adapter wrapping a fresh underlying player.
A volumechange reaches a subscribed handler and stops after PlayerAdapter.off; skipped when triggerVolumeChange returns false.
Calling PlayerAdapter.destroy twice does not throw.
Language-neutral PlayerAdapter conformance suite (Kotlin port of the web @dolby-optiview/ads-sdk-adapter-test-kit). Subclass it for a concrete adapter, provide createAdapter, and the inherited tests assert the shared contract every OptiView Ads PlayerAdapter must satisfy:
state properties (currentTime/duration/paused/muted/volume/programDateTime),
volume clamping to [0, 1] and mute pass-through,
subscription lifecycle (on/off, multiple handlers, idempotent destroy),
optional capabilities (preload, supportsParallelBuffering).
Event delivery is platform-dependent: it is only asserted when the platform can synthesize a player event headlessly (see triggerVolumeChange). On Android, ExoPlayer volume/playback events need real playback or a device, so delivery is covered by on-device integration; here it is skipped via Assume.
Create a fresh adapter wrapping a fresh underlying player.
A volumechange reaches a subscribed handler and stops after PlayerAdapter.off; skipped when triggerVolumeChange returns false.
Calling PlayerAdapter.destroy twice does not throw.
A fresh adapter reports position 0, an infinite duration and a paused player.
Setting PlayerAdapter.muted reads back the same value.
PlayerAdapter.preload of a URL does not throw.
PlayerAdapter.programDateTime is null before any stream is loaded.
PlayerAdapter.on and PlayerAdapter.off accept every PlayerAdapterEvent without throwing.
PlayerAdapter.supportsParallelBuffering is true, false or null.
Destroys the adapter created for the test; runs after every test.
Synthesize a volumechange on the adapter's underlying player so delivery can be asserted headlessly. Return false if the platform cannot trigger it without real playback/a device (the delivery test is then skipped).
PlayerAdapter.setVideoQuality with null returns false and does not throw.
Setting PlayerAdapter.volume reads back the same value, clamped to 0.0..1.0.
A fresh adapter reports position 0, an infinite duration and a paused player.
Setting PlayerAdapter.muted reads back the same value.
PlayerAdapter.preload of a URL does not throw.
PlayerAdapter.programDateTime is null before any stream is loaded.
PlayerAdapter.on and PlayerAdapter.off accept every PlayerAdapterEvent without throwing.
PlayerAdapter.supportsParallelBuffering is true, false or null.
Destroys the adapter created for the test; runs after every test.
Synthesize a volumechange on the adapter's underlying player so delivery can be asserted headlessly. Return false if the platform cannot trigger it without real playback/a device (the delivery test is then skipped).
PlayerAdapter.setVideoQuality with null returns false and does not throw.
Setting PlayerAdapter.volume reads back the same value, clamped to 0.0..1.0.
PlayerAdapterConformanceTest.
Language-neutral PlayerAdapter conformance suite (Kotlin port of the web @dolby-optiview/ads-sdk-adapter-test-kit). Subclass it for a concrete adapter, provide createAdapter, and the inherited tests assert the shared contract every OptiView Ads PlayerAdapter must satisfy:
The conformance test base for a custom PlayerAdapter. Extend PlayerAdapterConformanceTest in your test source set (testImplementation) to hold your adapter to the same contract the bundled adapters pass: event forwarding, state mirroring, seeking, and cleanup on destroy.
ContentVideoSizeProvider: lets the renderer confine break layouts to the video.
PlayerAdapter.currentTime from the main-thread snapshot, in seconds.
PlayerAdapter.destroy: removes the THEOplayer listeners; the player itself is left to the app.
PlayerAdapter.duration from the snapshot, in seconds.
THEOplayer implementation of the portable PlayerAdapter (PLAYG-398).
Wraps a Player the integrator owns — a plain THEOplayerView.player, or the native player resolved from a react-native-theoplayer view by the RN bridge — so the SDK drives THEOplayer-based content exactly like it drives Media3 through ExoPlayerAdapter. The adapter never owns the player: destroy detaches listeners and nothing else.
THEOplayer is main-thread-affine: its API must be called on the Android main thread. The SDK reads currentTime from whatever thread drives the scheduler ticker (Dispatchers.Default by default), so — like ExoPlayerAdapter — this adapter is safe from ANY thread:
Reads are served from a @Volatile snapshot refreshed ON the main thread, after every player callback and on a periodic poll (the playhead advances between callbacks).
Commands run inline when already on the main thread and are posted to it otherwise.
In-stream markers (HLS ID3 / EXT-X-DATERANGE / DASH emsg) arrive as cues on THEOplayer text tracks of kind metadata; the adapter subscribes to every such track as it appears and forwards each new cue as a TIMEDMETADATA event with a portable TimedMetadataCue payload (the Anvato signal path for ptsSource = ANVATO_CUE).
PlayerAdapter.currentTime from the main-thread snapshot, in seconds.
PlayerAdapter.duration from the snapshot, in seconds.
PlayerAdapter.isLive from the snapshot: whether THEOplayer reports an infinite duration.
PlayerAdapter.muted: reads the snapshot, writes on the main thread.
PlayerAdapter.paused from the snapshot.
Playback rate, read from the ENGINE rather than echoed from the last write.
PlayerAdapter.programDateTime: the stream's program date time at the current position, in milliseconds since the Unix epoch; null without one.
PlayerAdapter.volume (0.0 to 1.0): reads the snapshot, writes on the main thread.
ContentVideoSizeProvider: lets the renderer confine break layouts to the video.
PlayerAdapter.destroy: removes the THEOplayer listeners; the player itself is left to the app.
PlayerAdapter.load: sets url as the THEOplayer source on the main thread.
PlayerAdapter.off: removes a handler added with on.
PlayerAdapter.on: subscribes handler to event.
PlayerAdapter.pause on the main thread.
PlayerAdapter.play on the main thread.
PlayerAdapter.seek to time seconds on the main thread.
Pin the cheapest rendition by assigning a single VideoQuality to targetQuality, which both selects it and disables ABR for the track.
PlayerAdapter.isLive from the snapshot: whether THEOplayer reports an infinite duration.
PlayerAdapter.load: sets url as the THEOplayer source on the main thread.
PlayerAdapter.muted: reads the snapshot, writes on the main thread.
PlayerAdapter.off: removes a handler added with on.
PlayerAdapter.on: subscribes handler to event.
PlayerAdapter.pause on the main thread.
PlayerAdapter.paused from the snapshot.
PlayerAdapter.play on the main thread.
Playback rate, read from the ENGINE rather than echoed from the last write.
THEOplayer's own latency manager moves this to hold live latency, so the SDK compares observed against written to notice it is being overridden. Echoing the write would turn that check into a no-op and leave two controllers pulling against each other.
PlayerAdapter.programDateTime: the stream's program date time at the current position, in milliseconds since the Unix epoch; null without one.
PlayerAdapter.seek to time seconds on the main thread.
Pin the cheapest rendition by assigning a single VideoQuality to targetQuality, which both selects it and disables ABR for the track.
Returns false when there is nothing to choose between: a single-rendition ladder cannot be pinned lower, and reporting a pin that changed nothing would credit the break with a bandwidth saving it never made.
PlayerAdapter.volume (0.0 to 1.0): reads the snapshot, writes on the main thread.
THEOplayerAdapter.
THEOplayer implementation of the portable PlayerAdapter (PLAYG-398).
The PlayerAdapter for the OptiView Player (THEOplayer) on Android. THEOplayerAdapter wraps the Player of a THEOplayerView the app owns, so the SDK can drive THEOplayer-based playback exactly like Media3 through ExoPlayerAdapter. THEOplayer itself is not bundled: the app provides its own THEOplayer dependency and license.
The unconditional Android trust list: production, staging, and development backend keys.
The full catalog of known diagnostic codes, keyed by the stable code string.
SDK version embedded in diagnostic reports (monorepo lockstep version).
The catalog of diagnostic codes (DIAGNOSTIC_CODES) and the SDK version, generated from the shared taxonomy.
The manifest gained a channelId it did not have before.
The manifest's channelId changed to another value.
The manifest lost its channelId.
The manifest timebase changed while channelId stayed the same.
The GAM pod identity or the stitched-stream vendor identity changed while channelId stayed the same.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Why a polled Break Manifest counts as a switch to another ads channel. Carried on the adchannelchange event as its reason.
The manifest's channelId changed to another value.
The manifest gained a channelId it did not have before.
The manifest lost its channelId.
The GAM pod identity or the stitched-stream vendor identity changed while channelId stayed the same.
The manifest timebase changed while channelId stayed the same.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Map a manifest/config string to the type.
Returns null for an absent or unrecognised value — it must NOT fall back to REPLACEMENT (ADS-223): an unset insertion type is a distinct state, and only an unset one lets the manifest's resumeOffset drive the resume point. Folding absence into a concrete value here is what made the two indistinguishable.
Lookup of a manifest or configuration string.
Dynamic Ad Insertion: the ads are inserted into the content, so content resumes where it was interrupted.
Dynamic Ad Replacement: the ads replace content of the same length, so content resumes where it would have been.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Ad insertion type — how an ad break relates to the content timeline. Mirrors the TS AdInsertionType ('replacement' = DAR, 'insertion' = DAI).
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Conversions from plain values.
Text for a string, Unresolved for null — the legacy () -> String? meaning.
Text for a string, Unresolved for null — the legacy () -> String? meaning.
The parameter (or the cust_params pair) that contains the token is not sent.
The token is replaced by value.
No value: the token is kept literally and the parameter is sent.
What a macro resolves to when an ad request is built.
The parameter (or the cust_params pair) that contains the token is not sent.
The token is replaced by value.
No value: the token is kept literally and the parameter is sent.
A customer macro: a zero-argument callback evaluated every time an ad request is built, registered per token name in SessionConfig.assetParameterMacros. Return AssetParameterMacroValue.of of a string for a constant.
One candidate URI for an asset, with optional targeting (mirrors the TS AssetUri). Selected by Asset.resolveUri.
Per-asset ad parameters authored in the break manifest (the GAM adTagParameters for this asset). The lowest-precedence layer of the asset-parameter merge — SessionConfig.assetParameters and updateAssetParameters() override it per key.
Non-string values are dropped rather than coerced: the manifest spec types this as a string map, and a number silently stringified into a targeting key would change what is sent to GAM.
Companion creative shown alongside this asset — the second box of a double break, and the backdrop of an lshape_ad. Mirrors the web AssetWithCompanion.companion.
Until this existed the Kotlin model had no companion at all (its own doc comment deferred it to "the player phase"), so a double break reached the renderer with nothing to put in the second box and drew a single fullscreen ad instead — while still reporting format=double on every event, so the e2e suite passed on a visibly wrong render.
Typed as a nested Asset rather than a distinct class so a companion can itself carry uri/mediaType/duration exactly like a primary asset, matching web.
A single ad asset. Only the fields the SDK orchestrator/sequencer need are modeled here (the id drives the ad-event sequence); rich asset detail (uri/mediaType/companion/vendor params) is added in the player phase.
Per-asset ad parameters authored in the break manifest (the GAM adTagParameters for this asset). The lowest-precedence layer of the asset-parameter merge — SessionConfig.assetParameters and updateAssetParameters() override it per key.
Interaction options (click-through URL), when declared by the manifest.
Raw vendor parameters (decoded JSON map); parsed by the vendor integration (for GAM, into GamVendorParameters).
Resolve this asset's URI for deviceType, handling both the single-string and the targeted-array manifest shapes. Prefer this over reading Asset.uri directly.
Interaction options (click-through URL), when declared by the manifest.
For static assets: the direct media URL. For vendor (e.g. GAM pod) assets: the pod/ad-break identifier used to build the pod-manifest URL.
The manifest may instead carry an ARRAY of targeted candidates, which lands in uris. Read through Asset.resolveUri rather than touching either field, so both shapes work. TS models this as a string | AssetUri[] union on one field; Kotlin has no untagged unions, so it becomes two fields with one accessor.
Targeted URI candidates, when the manifest supplies an array instead of a plain string. Mutually exclusive with uri. Resolve via Asset.resolveUri.
Raw vendor parameters (decoded JSON map); parsed by the vendor integration (for GAM, into GamVendorParameters).
Content playback ended (a post-roll).
The viewer paused content (a pause ad).
Content playback started (a pre-roll).
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Lenient lookup; unknown/absent formats map to SINGLE.
This is NOT forward-compatible, whatever it used to claim — rendering an unrecognised format as a fullscreen single is the most invasive possible reading of a value we do not understand. It survives only as a rendering hint for variants that have already been SELECTED; known-ness is decided by BreakVariant.rawFormat, which selection filters on, so an unknown format never reaches a renderer (ADS-226).
Two zones: the main video area plus a companion area alongside.
The main video shrinks into a corner, the ad plays there, and a companion fills the backdrop.
The main video shrinks and keeps playing while the ad fills the backdrop.
The ad is rendered on top of the content, which keeps playing.
One slot covering the player surface.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
The supported break formats (mirrors the TS BreakFormat).
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Played seconds (>= 0) before any break may start; null means 0.
Ordered delivery-steering rules (first match wins), resolved once per session on the first manifest fetch; absent means sgai.
The root Break Manifest structure.
Played seconds (>= 0) before any break may start; null means 0.
Ordered delivery-steering rules (first match wins), resolved once per session on the first manifest fetch; absent means sgai.
Identifier of the organization owning the stream (ADS-303), surfaced on the CMCD ad telemetry.
Which time reference Break.start values use.
Session-level configuration per vendor integration (spec 1.1.0).
Identifier of the organization owning the stream (ADS-303), surfaced on the CMCD ad telemetry.
Which time reference Break.start values use.
Session-level configuration per vendor integration (spec 1.1.0).
A pre-roll that starts with the session.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
The only supported position value: a pre-roll relative to session start.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The layout this variant renders in; see rawFormat for the uncollapsed manifest string.
A break variant (format + ordered assets). The portable brain reads format/rawFormat/targeting/assets (variant selection — see selectVariantDetailed); the overlay layout fields (position/size/opacity) are resolved by the platform renderer and are populated only for BreakFormat.OVERLAY variants (null otherwise). Companion remains out of the portable model.
The layout this variant renders in; see rawFormat for the uncollapsed manifest string.
Overlay opacity 0.0-1.0; null defaults to fully opaque (BreakFormat.OVERLAY only).
Overlay placement within the player surface (BreakFormat.OVERLAY only).
The UNCOLLAPSED manifest format string. BreakFormat.from maps an unknown format to BreakFormat.SINGLE (forward-compatible parsing), but variant selection must treat an unknown format as NEVER playable — so the raw value survives here. Defaults to the enum's value.
Overlay size within the player surface (BreakFormat.OVERLAY only).
Variant-level targeting (manifest spec): a variant without a targeted deviceType is a default. Targeting.deviceType stays a raw string so an unrecognised value is targeted-but-unmatched (see Targeting).
Overlay opacity 0.0-1.0; null defaults to fully opaque (BreakFormat.OVERLAY only).
Overlay placement within the player surface (BreakFormat.OVERLAY only).
The UNCOLLAPSED manifest format string. BreakFormat.from maps an unknown format to BreakFormat.SINGLE (forward-compatible parsing), but variant selection must treat an unknown format as NEVER playable — so the raw value survives here. Defaults to the enum's value.
Overlay size within the player surface (BreakFormat.OVERLAY only).
Variant-level targeting (manifest spec): a variant without a targeted deviceType is a default. Targeting.deviceType stays a raw string so an unrecognised value is targeted-but-unmatched (see Targeting).
A single ad break. The portable brain (BreakScheduler) reads only id, start, and duration; the SDK orchestrator additionally uses controls (snapback/seek policy) and variants (to build the sequencer's SeqBreak).
Where content resumes after the break, in seconds from the break start; null resumes after duration.
Wallclock ISO string, PTS number, or an EventTrigger (spec 1.1.0 start.type: "event").
The variants the SDK selects from; see resolveBreakFormat.
Where content resumes after the break, in seconds from the break start; null resumes after duration.
Wallclock ISO string, PTS number, or an EventTrigger (spec 1.1.0 start.type: "event").
The variants the SDK selects from; see resolveBreakFormat.
Consecutive-break chaining (OptiViewAdsConfig.chaining): when one break ends and the next starts within maxGapSeconds, the SDK plays the next break at once instead of resuming content for the gap.
The largest gap in seconds between two breaks that still chains them.
Wallclock time source for the scheduler. Abstracts the system clock so a driver (e.g. the conformance harness) can step wallclock time deterministically. Mirrors Clock in packages/core/src/services/BreakScheduler.ts.
The current video dimensions, or null while they are not (yet) known.
Optional capability a PlayerAdapter can implement to report the content video's intrinsic dimensions.
The Android renderer uses this to confine break-format geometry (double boxes, L-shape pip, backdrop, overlay position/size) to the content video's DISPLAY rectangle — the aspect-fitted area actually showing video — instead of the full overlay container. On web the stage element wraps the video, so the CSS percentages are naturally video-relative; a fullscreen Android PlayerView is usually larger than the video it letterboxes, and without this capability the same fractions would (and previously did) spread the layout across the whole screen.
Lives in the core module so adapters that do not depend on the runtime (:ads-sdk-adapter-theoplayer) can implement it; it is player-agnostic — two ints. Adapters that do not implement it keep the historical container-relative layout.
Seconds into the break after which the viewer may skip it; null means not skippable.
Default for OptiViewAdsConfig.pdtGraceSeconds: how long a wallclock session waits for the stream's program date time.
Strict lookup: an unrecognised value is null, never a silent default.
Lookup of a manifest mode string.
Server-Guided Ad Insertion — the SDK schedules and renders breaks client-side.
Server-Side Ad Insertion — the content player plays a server-stitched stream.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Delivery architecture a DeliveryRule can select (mirrors the TS DeliveryMode).
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
One delivery-steering rule (mirrors the TS DeliveryRule). A rule without targeting matches every client (the manifest's default); a targeted rule matches only its device type.
mode keeps the raw manifest string for the same reason Targeting.deviceType does: an unrecognised value must stay distinguishable from an absent one, so resolveDeliveryMode can report it and fall back to sgai.
The delivery mode as written in the manifest; see DeliveryMode.
Strict lookup: an unrecognised value is null, never a silent default.
Lookup of a manifest deviceType string.
A desktop browser.
A phone.
A tablet (smallest width of 600dp or more on Android).
A television, including Android TV.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Device class used for per-URI asset targeting (mirrors the TS DeviceType).
This is the detected side of targeting — "what am I running on". The manifest side is Targeting, which deliberately keeps the raw string; see there for why.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Scheduling and playing a break.
Consecutive-break chaining.
Event dispatch to listeners.
Google Ad Manager pod serving.
SDK lifecycle such as destroy.
Fetching, parsing and validating the Break Manifest.
Content and ad playback, including the player adapter.
Preloading ad media before a break.
Session start, configuration and delivery mode.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Functional area a diagnostic relates to.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The functional area of the code.
Static metadata describing a diagnostic code.
The severity every diagnostic with this code has.
Verbose detail for debugging.
Something failed.
Normal operation worth recording.
Something degraded but playback continues.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Severity of a diagnostic record.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The ad is audible, content is silenced for the break. The default.
Content stays audible, the ad is silenced for the break.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Which side keeps audio during a double-format break.
double is the one format where content and ad are BOTH on screen and BOTH playing, so it is the one format where two soundtracks can run at once. Exactly one side is audible for the break's duration; the other is silenced and restored when it ends.
Mirrors the web DoubleBoxAudio.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The triggering playback event as written in the manifest; see BreakEvent.
The triggering playback event as written in the manifest; see BreakEvent.
1-based position of this ad within the pod (getAdPosition()); null when IMA reports none.
IMA's creative id, when available (getCreativeId()).
One IMA pod-ad report, normalized off AdEvent.getAd().getAdPodInfo() by the render layer so this module never sees an IMA object.
The custom asset key of the pod-serving stream.
The GAM stream identity, as used to create the IMA/DAI session.
Both fields are required: a session created with a blank network code or custom asset key produces a pod URL like .../network//custom_asset/..., and the 404 that comes back reads as a GAM outage rather than as the configuration error it is.
The Google Ad Manager network code.
The custom asset key of the pod-serving stream.
The Early Ad Break Notification version, V1 or V2.
The vendorParameters of a GAM pod-serving asset, validated. The EABN version selects the pod URL path segment (/pod/ vs /ad_break_id/).
The custom asset key of the pod-serving stream.
The Early Ad Break Notification version, V1 or V2.
The Google Ad Manager network code.
The Google Ad Manager network code.
Overlay when possible, shared element when the platform requires it.
Ads play in the SDK's own player stacked above the content player.
Ads play in the content player itself (platforms with a single video element).
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Resolved ad-insertion strategy: the auto sentinel resolves to one of these.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
URL to open when the viewer clicks/taps the ad. The SDK never opens it itself.
Interaction options for an asset (mirrors the TS Interaction).
The header carrying the detached JWS over the manifest response body.
Parses and validates break manifests. Mirrors the validation in packages/core/src/services/ManifestService.ts (parseManifest) — error messages are part of the cross-language contract and must match the TS reference byte-for-byte (the conformance harness diffs them).
Forward-compatible: unknown top-level fields are ignored.
Validate already-decoded manifest data (a JSON object as a Map) and build a typed BreakManifest. Throws IllegalArgumentException with a message identical to the TS reference on any validation failure.
Validate already-decoded manifest data (a JSON object as a Map) and build a typed BreakManifest. Throws IllegalArgumentException with a message identical to the TS reference on any validation failure.
The duration of the break being requested, in whole milliseconds.
The duration of the break being requested, in whole seconds.
The height of the ad container in dp.
The width of the ad container in dp.
The device's HTTP user agent (System.getProperty("http.agent")).
The built-in asset-parameter macros the SDK resolves itself. A customer macro registered under one of these names in SessionConfig.assetParameterMacros takes precedence over the built-in value.
The duration of the break being requested, in whole milliseconds.
The duration of the break being requested, in whole seconds.
The height of the ad container in dp.
The width of the ad container in dp.
The device's HTTP user agent (System.getProperty("http.agent")).
Marks a declaration the SDK modules share with each other but that is not part of the supported public API: it can change or disappear in any release and is left out of the API reference. Using it from an app produces a compiler warning; opt in with @OptIn(OptiViewInternalApi::class) to accept that.
Position of an overlay ad within the player surface, as fractions 0.0-1.0 of the surface (mirrors the TS OverlayPosition). Only one of {top, bottom} and one of {left, right} is typically supplied; the renderer converts these to platform layout. Brain-agnostic — only the overlay renderer reads them.
The resolved pause ad to display: the originating break, its single asset, how the asset is sourced, and whether it is an image or a video. The renderer uses source to decide whether to load the URL directly (static) or fetch + parse the VAST creative first (vast), and mediaType to decide whether to render an image overlay or a muted, play-once video. Mirrors the TS PauseAdResolution.
A player event handler. The optional payload carries adapter-specific detail (e.g. a media error or TimedMetadataCue).
Playback reached the end of the content.
The player failed; the payload is the player's error.
Playback paused (drives pause ads).
Playback started or resumed.
A seek completed; the SDK enforces snapback on it.
An in-stream timed-metadata marker; the payload is a TimedMetadataCue.
The playback position advanced; the SDK schedules breaks on it.
Volume or mute state changed.
Playback stalled waiting for data.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Event types a PlayerAdapter must forward (mirrors the TS PlayerAdapterEvent).
TIMEDMETADATA is optional/capability-style: content adapters used for SSAI playback emit it for each in-stream timed-metadata marker (HLS ID3 / EXT-X-DATERANGE) with a TimedMetadataCue payload, so the SDK can forward markers to IMA for ad tracking. Adapters that cannot surface metadata never emit it.
The playback position advanced; the SDK schedules breaks on it.
Volume or mute state changed.
An in-stream timed-metadata marker; the payload is a TimedMetadataCue.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Current playback time in seconds.
Clean up resources (called when the SDK is destroyed).
Total content duration in seconds; Double.POSITIVE_INFINITY for live.
The abstraction layer between the SDK and any content player — the Kotlin mirror of packages/core/src/interfaces/PlayerAdapter.ts.
The SDK core only interacts with players through this interface, so the brain stays player-agnostic and never imports Media3/ExoPlayer. The portable brain (BreakScheduler) reads only currentTime; the rest of the contract is used by the SDK orchestrator and the platform ad renderer.
Android idiom: unlike the web adapter (whose load/play return Promises), load/play are synchronous here — they kick off preparation/playback and return immediately; readiness/completion is signalled via PlayerAdapterEvents (e.g. playing, waiting, ended). There is also no web-only videoElement.
Current playback time in seconds.
Total content duration in seconds; Double.POSITIVE_INFINITY for live.
Optional hint: whether the loaded content is a LIVE (dynamic-timeline) stream. On live content duration is not a reliable signal on Android — ExoPlayer reports the (finite) sliding-window duration — so the runtime uses this to restore the viewer's live latency after a break that paused content, regardless of the channel's break timebase. Null means unknown and is treated as not live.
The furthest position on this player's timeline a seek will actually STICK on live content, in seconds — the engine pulls back anything closer to the live edge.
Playback rate, where 1.0 is normal speed. Optional, and settable.
Whether currentTime is measured from the START OF A SLIDING WINDOW rather than from a fixed origin.
Program Date Time from the stream (EXT-X-PROGRAM-DATE-TIME for HLS), as epoch milliseconds, used for wallclock-timebase break matching. Null when unavailable. (Epoch ms rather than a Date/Instant to keep the brain dependency-free and conformance-portable.)
Optional capability hint: whether this adapter/platform can buffer a second media source in parallel with the content player without decoder contention. Null is treated as true by the auto preload resolver.
Unsubscribe a previously registered handler.
Subscribe to a player event.
Optionally select a content quality, or pass null to release the SDK's override. A successful VideoQuality.LOWEST request snapshots the integrator's current selection and applies the cheapest rendition without flushing. Returns true only when the requested override was applied or restoration of an outstanding override was successfully attempted.
Optional hint: whether the loaded content is a LIVE (dynamic-timeline) stream. On live content duration is not a reliable signal on Android — ExoPlayer reports the (finite) sliding-window duration — so the runtime uses this to restore the viewer's live latency after a break that paused content, regardless of the channel's break timebase. Null means unknown and is treated as not live.
The furthest position on this player's timeline a seek will actually STICK on live content, in seconds — the engine pulls back anything closer to the live edge.
Return null when the engine cannot say, and on non-live content — null is safe: the SDK then does not clamp. Never guess: a guessed holdback — 18s only fits 6s segments — could place content worse than not clamping at all.
Why it exists: every engine enforces a minimum live offset it will not let playback sit inside. Seek past it and the engine quietly pulls back, so a target computed without it is a request the player is free to ignore.
Computed engine-side from whichever pair the engine exposes:
maxLiveSeekPosition = currentTime + currentLiveOffset - minimumOffsetOn ExoPlayer that is Player.getCurrentLiveOffset() against MediaItem.LiveConfiguration.minOffsetMs (both present in media3 1.4.1). Deriving it from the offset pair rather than from the seekable range keeps the core arithmetic identical across TS, Kotlin and Swift.
Unsubscribe a previously registered handler.
Subscribe to a player event.
Pause playback (called when an ad break starts).
Resume playback (called when an ad break ends). Returns immediately.
Playback rate, where 1.0 is normal speed. Optional, and settable.
Used ONLY by continueContentDuringBreak, and only while content is hidden and muted: a content stall is the one thing that makes content drift from the break timeline, and a forward seek cannot repair it — content playing at the live edge has its seek window bounded by the same holdback the resume seek runs into. Rate is the only lever left.
Adapters MUST report what the engine actually has, not the last value written. ExoPlayer and THEOplayer both drive this themselves for live sync, and the SDK detects being overridden by comparing observed against written — an adapter echoing its own write turns that check into a no-op and leaves two controllers pulling against each other.
The default is an inert 1.0: an adapter that cannot set a rate simply gets no correction, and the drift is carried and reported instead.
Whether currentTime is measured from the START OF A SLIDING WINDOW rather than from a fixed origin.
ExoPlayer reports live positions this way: Player.getCurrentPosition() is relative to the current Timeline.Window, whose start advances as segments age out. The consequence inverts every intuition built on the web contract — content playing at the live edge reports a roughly CONSTANT position, and a player falling behind reports a DECREASING one, because the window slides underneath it at real time.
Anything comparing position against elapsed wall time must know this. Measured on a Galaxy Tab S11 on 2026-08-25: continueContentDuringBreak computed expected = anchor + elapsedWall, which on a window-relative timeline runs away by the whole break, so a healthy break reported -155.9s of drift and raised a warning about it while the proxy showed content fetching 73 segments without a gap. The number was wrong, not the playback.
False is the safe default: an absolute timeline is what the web engines provide and what every existing calculation already assumes.
Program Date Time from the stream (EXT-X-PROGRAM-DATE-TIME for HLS), as epoch milliseconds, used for wallclock-timebase break matching. Null when unavailable. (Epoch ms rather than a Date/Instant to keep the brain dependency-free and conformance-portable.)
Optionally select a content quality, or pass null to release the SDK's override. A successful VideoQuality.LOWEST request snapshots the integrator's current selection and applies the cheapest rendition without flushing. Returns true only when the requested override was applied or restoration of an outstanding override was successfully attempted.
Optional capability hint: whether this adapter/platform can buffer a second media source in parallel with the content player without decoder contention. Null is treated as true by the auto preload resolver.
No preloading; the ad loads when the break starts.
The ad buffers in a second decoder while content keeps playing.
Only one decoder is available, so the ad is prepared without buffering ahead.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Resolved preload strategy: the auto sentinel resolves to one of these.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Thrown when the manifest steers the session to ssai but no vendor configuration can provide a stitched stream. Deliberately catchable by the application (no silent fallback to sgai): the app decides which stream to play instead.
ssai[0].assetParameters: the manifest session layer for the stitched stream.
The Google Ad Manager network code.
The targeted device class as written in the manifest (desktop, mobile, tablet, tv); null targets every device.
Targeting criteria attached to an AssetUri (mirrors the TS Targeting).
deviceType is a raw String, NOT the DeviceType enum, and that is deliberate. The TS DeviceType is a string enum, so at runtime an unrecognised value such as "foldable" stays a plain string: it does not equal the detected device, and it is not undefined, so resolveTargetedUri treats the entry as targeted-but-unmatched and skips it rather than adopting it as the untargeted default. Parsing into a nullable enum would collapse "unknown value" and "no value" into the same null and silently promote a foreign entry to the fallback — a real behavioural divergence on exactly the manifests a forward-compatible parser is supposed to tolerate.
Seconds from the start of the asset, matched against the playback position; VOD only.
A presentation timestamp in seconds (may be fractional); live streams.
An absolute ISO-8601 timestamp.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
ID3 frame description/info (e.g. the GEOB frame description — Anvatos for Anvato break-signaling cues), when the platform parser surfaces it.
A single in-stream timed-metadata marker surfaced by a content player — the Kotlin mirror of the TS TimedMetadataCue. Carried as the payload of a TIMEDMETADATA event; in SSAI mode the SDK forwards it to the IMA DAI stream manager for ad tracking.
ID3 frame description/info (e.g. the GEOB frame description — Anvatos for Anvato break-signaling cues), when the platform parser surfaces it.
Free-form message payload: emsg message data, daterange client attribute, or the decoded (UTF-8) data of an ID3 GEOB frame.
WHEN this delivery happened, relative to the cue's own startTime: "parsed" when the carrying segment was demuxed (early — 20-30s on hls.js against the live NFL feed, which is what gives a break its preload window), "presented" when the playhead has just reached it (frame-accurate — p90 under 10ms, ADS-285).
Scheme URI (EXT-X-DATERANGE scheme / emsg schemeIdUri).
Free-form message payload: emsg message data, daterange client attribute, or the decoded (UTF-8) data of an ID3 GEOB frame.
WHEN this delivery happened, relative to the cue's own startTime: "parsed" when the carrying segment was demuxed (early — 20-30s on hls.js against the live NFL feed, which is what gives a break its preload window), "presented" when the playhead has just reached it (frame-accurate — p90 under 10ms, ADS-285).
ExoPlayer's onMetadata delivers at PRESENTATION, so this adapter's cues are "presented"; hls.js delivers at parse. One event name has meant both things depending on the platform, and that asymmetry is why native has no preload window at all (ADS-286: 6ms of lead measured on an S11).
null means unknown and MUST keep today's behaviour: mislabelling parsed as presented would fire every break 20-30s early, which is the one failure this distinction exists to prevent.
Scheme URI (EXT-X-DATERANGE scheme / emsg schemeIdUri).
Tune-in, or join-in-progress (OptiViewAdsConfig.tuneIn): a viewer who joins while a break is already running sees the remainder of that break, unless less than minBreakDurationSeconds of it is left.
The shortest remaining break length in seconds that is still played.
Detected device class; null = unknown (targeted variants never match).
Inputs the platform layer feeds into a selection (mirrors the TS shape).
Playable formats in the CURRENT context; null = every renderable format.
An ad playback error that carries the ad vendor's own error code (e.g. the numeric IMA/VAST AdError code), so telemetry can report it (adevc) alongside the SDK's taxonomy code. Vendor integrations wrap their errors in this type when the vendor supplies a code; errors without one stay plain exceptions.
The Kotlin mirror of packages/core/src/types/VendorAdError.ts.
The vendor's error code, stringified (e.g. IMA's numeric AdError code).
Session-level configuration for one vendor integration.
Discriminated by type, which uses the same vendor identifiers as an asset's vendor field. Per the spec a manifest carries AT MOST ONE entry per type; a player reads the first entry of a given type and ignores (and logs) types it does not recognise.
values keeps the entry's raw fields rather than modelling each vendor's shape, so an entry for a vendor this SDK version has never heard of survives parsing intact.
The lowest rendition the player offers, without flushing the buffer.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
A quality target understood by the optional PlayerAdapter.setVideoQuality operation.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The playback event that triggers brk (spec event or legacy position), or null for a timeline break.
Look up the metadata for a known diagnostic code, or null if unknown.
Seconds after content playback ends before a post-roll triggers, or null when brk is not a post-roll.
Pre-roll delay in seconds of played content, or null when brk is not a START pre-roll.
Whether a pre-roll fires as soon as content playback starts: a delay: 0 pre-roll with no adStartDelay (an ad-free start would swallow it).
The Break Manifest model (BreakManifest, Break, Asset, BreakFormat, Timebase), the PlayerAdapter contract with its events and timed-metadata cues, the preload / insertion / delivery mode types, the exceptions the SDK throws, and the diagnostic category and level types.
Why a polled Break Manifest counts as a switch to another ads channel. Carried on the adchannelchange event as its reason.
Ad insertion type — how an ad break relates to the content timeline. Mirrors the TS AdInsertionType ('replacement' = DAR, 'insertion' = DAI).
A single ad asset. Only the fields the SDK orchestrator/sequencer need are modeled here (the id drives the ad-event sequence); rich asset detail (uri/mediaType/companion/vendor params) is added in the player phase.
A customer macro: a zero-argument callback evaluated every time an ad request is built, registered per token name in SessionConfig.assetParameterMacros. Return AssetParameterMacroValue.of of a string for a constant.
What a macro resolves to when an ad request is built.
The supported break formats (mirrors the TS BreakFormat).
The root Break Manifest structure.
The only supported position value: a pre-roll relative to session start.
A break variant (format + ordered assets). The portable brain reads format/rawFormat/targeting/assets (variant selection — see selectVariantDetailed); the overlay layout fields (position/size/opacity) are resolved by the platform renderer and are populated only for BreakFormat.OVERLAY variants (null otherwise). Companion remains out of the portable model.
Pre-break warnings (OptiViewAdsConfig.breakWarnings): the SDK emits an adbreakstatus event with phase = upcoming at each threshold.
Consecutive-break chaining (OptiViewAdsConfig.chaining): when one break ends and the next starts within maxGapSeconds, the SDK plays the next break at once instead of resuming content for the gap.
Intrinsic pixel dimensions of the content video, as reported by the player.
Optional capability a PlayerAdapter can implement to report the content video's intrinsic dimensions.
Delivery architecture a DeliveryRule can select (mirrors the TS DeliveryMode).
One delivery-steering rule (mirrors the TS DeliveryRule). A rule without targeting matches every client (the manifest's default); a targeted rule matches only its device type.
Device class used for per-URI asset targeting (mirrors the TS DeviceType).
Functional area a diagnostic relates to.
Static metadata describing a diagnostic code.
Severity of a diagnostic record.
Which side keeps audio during a double-format break.
One IMA pod-ad report, normalized off AdEvent.getAd().getAdPodInfo() by the render layer so this module never sees an IMA object.
The GAM stream identity, as used to create the IMA/DAI session.
The vendorParameters of a GAM pod-serving asset, validated. The EABN version selects the pod URL path segment (/pod/ vs /ad_break_id/).
Resolved ad-insertion strategy: the auto sentinel resolves to one of these.
Interaction options for an asset (mirrors the TS Interaction).
Parses and validates break manifests. Mirrors the validation in packages/core/src/services/ManifestService.ts (parseManifest) — error messages are part of the cross-language contract and must match the TS reference byte-for-byte (the conformance harness diffs them).
A trusted Ed25519 verification key, resolved by the protected kid.
The built-in asset-parameter macros the SDK resolves itself. A customer macro registered under one of these names in SessionConfig.assetParameterMacros takes precedence over the built-in value.
Marks a declaration the SDK modules share with each other but that is not part of the supported public API: it can change or disappear in any release and is left out of the API reference. Using it from an app produces a compiler warning; opt in with @OptIn(OptiViewInternalApi::class) to accept that.
Position of an overlay ad within the player surface, as fractions 0.0-1.0 of the surface (mirrors the TS OverlayPosition). Only one of {top, bottom} and one of {left, right} is typically supplied; the renderer converts these to platform layout. Brain-agnostic — only the overlay renderer reads them.
Size of an overlay ad as fractions 0.0-1.0 of the player surface (mirrors the TS OverlaySize).
The resolved pause ad to display: the originating break, its single asset, how the asset is sourced, and whether it is an image or a video. The renderer uses source to decide whether to load the URL directly (static) or fetch + parse the VAST creative first (vast), and mediaType to decide whether to render an image overlay or a muted, play-once video. Mirrors the TS PauseAdResolution.
The abstraction layer between the SDK and any content player — the Kotlin mirror of packages/core/src/interfaces/PlayerAdapter.ts.
Event types a PlayerAdapter must forward (mirrors the TS PlayerAdapterEvent).
A player event handler. The optional payload carries adapter-specific detail (e.g. a media error or TimedMetadataCue).
Resolved preload strategy: the auto sentinel resolves to one of these.
Thrown when the manifest steers the session to ssai but no vendor configuration can provide a stitched stream. Deliberately catchable by the application (no silent fallback to sgai): the app decides which stream to play instead.
A single in-stream timed-metadata marker surfaced by a content player — the Kotlin mirror of the TS TimedMetadataCue. Carried as the payload of a TIMEDMETADATA event; in SSAI mode the SDK forwards it to the IMA DAI stream manager for ad tracking.
Tune-in, or join-in-progress (OptiViewAdsConfig.tuneIn): a viewer who joins while a break is already running sees the remainder of that break, unless less than minBreakDurationSeconds of it is left.
Inputs the platform layer feeds into a selection (mirrors the TS shape).
An ad playback error that carries the ad vendor's own error code (e.g. the numeric IMA/VAST AdError code), so telemetry can report it (adevc) alongside the SDK's taxonomy code. Vendor integrations wrap their errors in this type when the vendor supplies a code; errors without one stay plain exceptions.
Session-level configuration for one vendor integration.
A quality target understood by the optional PlayerAdapter.setVideoQuality operation.
Default for OptiViewAdsConfig.pdtGraceSeconds: how long a wallclock session waits for the stream's program date time.
The header carrying the detached JWS over the manifest response body.
Default Clock backed by the system clock.
The playback event that triggers brk (spec event or legacy position), or null for a timeline break.
Look up the metadata for a known diagnostic code, or null if unknown.
Seconds after content playback ends before a post-roll triggers, or null when brk is not a post-roll.
Pre-roll delay in seconds of played content, or null when brk is not a START pre-roll.
Whether a pre-roll fires as soon as content playback starts: a delay: 0 pre-roll with no adStartDelay (an ad-free start would swallow it).
True when start is an EventTrigger rather than a timebase position.
True when brk is a pause ad: its start is an EventTrigger for BreakEvent.PAUSE.
Whether the break is a post-roll: start: { type: 'event', event: 'end' }.
Resolve the declared ad format of a break — the first (selected) variant's BreakFormat (PLAYG-182), mirroring the TS resolveBreakFormat. Surfaced on the public break/ad events. Null when the break declares no variant.
Resolve this asset's URI for deviceType, handling both the single-string and the targeted-array manifest shapes. Prefer this over reading Asset.uri directly.
True when start is an EventTrigger rather than a timebase position.
True when brk is a pause ad: its start is an EventTrigger for BreakEvent.PAUSE.
Whether the break is a post-roll: start: { type: 'event', event: 'end' }.
The Asset carrying assetId within brk, searched across every variant.
The SDK's ad events identify an asset by id, but the web events expose the whole asset object — so consumers reading event.asset.uri to report which creative played need the id resolved back to the model. Sits beside resolveBreakFormat because it is the same kind of pure lookup over the manifest.
Null when the id does not resolve — a vendor pod whose real creatives come from the ad server, or an id belonging to a chained successor — rather than inventing an asset.
Resolve the declared ad format of a break — the first (selected) variant's BreakFormat (PLAYG-182), mirroring the TS resolveBreakFormat. Surfaced on the public break/ad events. Null when the break declares no variant.
Resolve this asset's URI for deviceType, handling both the single-string and the targeted-array manifest shapes. Prefer this over reading Asset.uri directly.
The media URL to play, or null when the asset has no candidate for this device.
The device the asset will play on; null selects the untargeted candidate.
Default Clock backed by the system clock.
The portable core of the OptiView Ads SDK: pure Kotlin/JVM with no Android or player dependencies. It holds the types the rest of the SDK is expressed in — the Break Manifest model, the PlayerAdapter contract a content player is driven through, the ad-insertion and delivery modes, and the diagnostic code taxonomy. Integrators rarely depend on it directly; ads-sdk-runtime and ads-sdk bring it transitively.
What the renderer does when the system moves audio focus around during a break. Split from the platform calls so unit tests can drive focus transitions directly.
Another app wants to be heard over us briefly — duck the ad's volume.
Focus came back after a transient loss/duck — restore volume and resume.
Focus was lost (permanently or transiently) — pause the ad.
Another app wants to be heard over us briefly — duck the ad's volume.
Focus came back after a transient loss/duck — restore volume and resume.
Focus was lost (permanently or transiently) — pause the ad.
Focus was already held from an earlier request.
The system refused focus; the ad plays without it.
Focus was granted for this request.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Outcome of an AdAudioFocus.request.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
The renderer's handle on audio focus for ad playback. request/abandon bracket a break; focus transitions while held arrive via AdAudioFocusCallbacks.
Take (or keep) media audio focus for ad playback. Idempotent.
Aspect-fill: the creative covers the surface and the overflow is cropped.
Aspect-fit: the whole creative is visible, letterboxed where the aspect ratio differs.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
How ad creatives scale inside the ad surface — the Kotlin mirror of the iOS runtime's AdScaling.
FIT: aspect-fit — the whole creative is visible; an aspect mismatch with the surface letterboxes against black bars.
FILL: aspect-fill — the creative covers the whole ad surface and the overflow is cropped symmetrically (never stretched). This is an explicit opt-in for creatives that should cover the ad surface. The web renderer's primary ad creatives use object-fit: contain; only companion/backdrop artwork uses object-fit: cover.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Platform AdAudioFocus over AudioManager.
The SDK plays ads on its own ExoPlayer while the content player is paused — and pausing content makes typical integrations (e.g. react-native-theoplayer's AudioFocusManager) abandon the app's focus. Without this, the whole break plays against an EMPTY focus stack: an incoming call cannot pause/duck the ad and other apps' audio mixes over it (PLAYG-458). Holding AUDIOFOCUS_GAIN with USAGE_MEDIA for the duration of the break restores normal system focus semantics to ad playback.
Take (or keep) media audio focus for ad playback. Idempotent.
ContentVideoSizeProvider: lets the renderer confine break layouts to the video.
PlayerAdapter.currentTime from the application-thread snapshot, in seconds.
PlayerAdapter.destroy: detaches from the player and stops the snapshot poll; the player itself is left to the app.
PlayerAdapter.duration from the snapshot, in seconds; the live window length for live streams.
Media3/ExoPlayer implementation of the portable PlayerAdapter (P4b-2).
Wraps an ExoPlayer the integrator owns (created and attached to their own PlayerView); the SDK only ever drives the content player through this adapter, keeping the brain player-agnostic. A single Player.Listener fans Media3 callbacks out to the adapter's PlayerAdapterEvent handlers.
ExoPlayer is thread-affine: every access must happen on its application thread (ExoPlayer.applicationLooper, normally the main thread) or it throws IllegalStateException: Player is accessed on the wrong thread.
The SDK cannot honour that from the caller's side. BreakScheduler.tick() reads currentTime on whatever thread drives the ticker, and both OptiViewAds's default scope and a plainly-constructed CoroutineSchedulerTicker use Dispatchers.Default — so ticking crashed on the very first tick unless the integrator happened to pass a Dispatchers.Main scope (which is the only reason the demo apps worked).
This adapter therefore makes itself safe from ANY thread:
Reads (currentTime, duration, paused, muted, volume, programDateTime) are served from a @Volatile snapshot refreshed ON the application thread — after every listener callback and on a periodic poll (position advances between callbacks, so events alone are not enough).
Commands (pause, play, seek, load, and the muted/volume setters) run inline when already on the application thread, and are posted to it otherwise.
PlayerAdapter.currentTime from the application-thread snapshot, in seconds.
PlayerAdapter.duration from the snapshot, in seconds; the live window length for live streams.
PlayerAdapter.isLive from the snapshot: whether the current Media3 window is live.
PlayerAdapter.muted: reads the snapshot, writes on the application thread.
PlayerAdapter.paused from the snapshot.
Playback speed, read from the ENGINE rather than echoed back from the last write.
True on live: media3's getCurrentPosition() is relative to the current Timeline.Window, whose start advances as the live window slides. See the contract for what that breaks.
Wallclock of the current playhead (epoch ms) for HLS EXT-X-PROGRAM-DATE-TIME matching, derived from the live window's start time plus the position in the window. Null when the timeline carries no wallclock anchor (VOD/no PDT).
PlayerAdapter.volume (0.0 to 1.0): reads the snapshot, writes on the application thread.
ContentVideoSizeProvider: lets the renderer confine break layouts to the video.
PlayerAdapter.destroy: detaches from the player and stops the snapshot poll; the player itself is left to the app.
PlayerAdapter.load: sets url as the player's media item and prepares it, on the application thread.
PlayerAdapter.off: removes a handler added with on.
PlayerAdapter.on: subscribes handler to event.
PlayerAdapter.pause on the application thread.
PlayerAdapter.play on the application thread.
Pin to the cheapest rendition with setMaxVideoBitrate, not by selecting a track.
PlayerAdapter.isLive from the snapshot: whether the current Media3 window is live.
PlayerAdapter.load: sets url as the player's media item and prepares it, on the application thread.
PlayerAdapter.muted: reads the snapshot, writes on the application thread.
PlayerAdapter.off: removes a handler added with on.
PlayerAdapter.on: subscribes handler to event.
PlayerAdapter.pause on the application thread.
PlayerAdapter.paused from the snapshot.
PlayerAdapter.play on the application thread.
Playback speed, read from the ENGINE rather than echoed back from the last write.
media3's own MediaItem.LiveConfiguration speed adjustment moves this to hold live latency, so the SDK compares observed against written to notice it is being overridden. Echoing the write would turn that check into a no-op and leave two controllers fighting.
True on live: media3's getCurrentPosition() is relative to the current Timeline.Window, whose start advances as the live window slides. See the contract for what that breaks.
Wallclock of the current playhead (epoch ms) for HLS EXT-X-PROGRAM-DATE-TIME matching, derived from the live window's start time plus the position in the window. Null when the timeline carries no wallclock anchor (VOD/no PDT).
SDK-owned post-break resume seek: keyframe-aligned via CLOSEST_SYNC, the same parameters as seek.
The history matters, because both alternatives shipped and both failed on devices:
EXACT (PLAYG-496, beta.224): decodes from the preceding keyframe to the target — the measured ~1.4-2.2s post-break hole ("content is PAUSED at end of window" across D1/D5/D7/E7, F8 past the window).
NEXT_SYNC (beta.227): never lands before the cue, but has NO CLAMP at the media end — a resume point past the last sync sample snaps into STATE_ENDED and the following play() is a no-op (12 scenarios red: D3/D4/D6/D7/F8/J5/P-SHAKA-HLS/J1/J6, "content never resumes").
CLOSEST_SYNC lands at-or-before the target on the nearest keyframe: fast (~0.3-0.7s resume), can never overshoot the media end, and the one property it gives up — "never before the cue" — is already covered by the cross-core scheduler's resume-seek guard, which tolerates a keyframe-snapped undershoot without re-arming the completed break (PLAYG-371/PLAYG-496; the guard is what actually protects rn-video's native adjustments too). Kept as a separate method because other adapters (react-native-video) route their own semantics through the PlayerAdapter.seekExact default.
Seek the content player, snapping to the nearest sync sample.
ExoPlayer defaults to EXACT seeking, which must decode from the preceding keyframe up to the target — on a post-break resume that showed up as a visible hole between the ad ending and content reappearing. Measured on a Galaxy Tab, adbreakend -> content playing: ~2.2s on VOD (1658ms of it seek recovery) and ~1.4s on live (1257ms). The gap arrived with the resume-seek itself: resolveResumePoint was dead code, so Android used to resume instantly — at the wrong position.
Frame accuracy buys nothing here. A DAI resume targets the CUE, which is where a break was inserted and therefore already at or near a segment boundary, and a live latency restore is recovering ~10s. Up to one GOP of drift is irrelevant against either.
Scoped rather than global: SeekParameters is a player-wide setting, and the integrator owns this player. The previous value is restored immediately, so the app's OWN seeks (DVR scrubbing, which never come through this adapter) keep exact behaviour.
Pin to the cheapest rendition with setMaxVideoBitrate, not by selecting a track.
A bitrate ceiling keeps ABR ENABLED underneath it, so the engine still adapts within what is left and still recovers on its own if the lowest rendition itself stalls. Overriding the selection outright would take that away for the whole break.
Deliberately not setForceLowestBitrate: that is a session-wide policy flag the integrator may own, whereas the ceiling is a value we can snapshot and hand straight back — the same reason seek snapshots and restores seekParameters rather than setting a global.
Returns false when the ladder gives nothing to choose between: a single rendition cannot be pinned lower, and reporting a pin that changed nothing would credit the break with a bandwidth saving it never made.
PlayerAdapter.volume (0.0 to 1.0): reads the snapshot, writes on the application thread.
Callbacks for IMA ad-progress events (mirrors the web GamAdEventCallbacks).
IMA finished an ad break (a pod).
IMA started an ad break (a pod).
The current ad within the pod completed.
The current ad reached 25%.
The current ad reached 50%.
An ad within the pod started. info carries the pod-ad data normalized off IMA's AdPodInfo (GamPodAdInfo), or null when IMA attached no ad to the event — nothing downstream of GamStreamManager handles IMA types.
The current ad reached 75%.
IMA finished an ad break (a pod).
IMA started an ad break (a pod).
The current ad within the pod completed.
The current ad reached 25%.
The current ad reached 50%.
An ad within the pod started. info carries the pod-ad data normalized off IMA's AdPodInfo (GamPodAdInfo), or null when IMA attached no ad to the event — nothing downstream of GamStreamManager handles IMA types.
The current ad reached 75%.
Ad tag parameters sent with the stream request (targeting, custom parameters).
Configuration for a full-service IMA DAI live-stream session (ADS-326 steered ssai): the ads are stitched by Google and the SDK plays the single returned stream, so this carries the DAI assetKey rather than the pod-serving customAssetKey.
The IMA stream activity monitor id, for debugging sessions with Google.
Ad tag parameters sent with the stream request (targeting, custom parameters).
The custom asset key of the pod-serving stream.
Ad tag parameters sent with the stream request (targeting, custom parameters).
The custom asset key of the pod-serving stream.
The Google Ad Manager network code.
The IMA stream activity monitor id, for debugging sessions with Google.
The Google Ad Manager network code.
The IMA stream activity monitor id, for debugging sessions with Google.
Destroy and release all resources.
The IMA stream id of the initialized session, or null before isInitialized.
Manages a Google IMA DAI SDK pod-serving session on Android — the Kotlin mirror of the web GamStreamManager. Initializes an IMA StreamManager via a PodStreamRequest, exposes the resulting streamId for pod-manifest URL construction (delegated to the portable buildGamPodUrl), and forwards ad progress/quartile events.
Pod manifests are stitched/played by the SDK's ad player (we build the pod URL ourselves); IMA tracks ad progress from the stream's timed metadata, which the player forwards via processMetadata. Requires a device/emulator at runtime (the IMA SDK has no headless mode); this class is structured for that.
The IMA stream id of the initialized session, or null before isInitialized.
Initialize a fresh IMA pod-serving session and suspend until the stream id is available (or the request errors). Always resets any prior session.
Open a full-service IMA DAI live-stream session and suspend until IMA hands back the stitched stream URL to play on the content player.
Whether a stream session has been initialized with a valid streamId.
Forward timed metadata (HLS ID3 TXXX text) from the ad player to IMA.
Forward an in-stream timed-metadata marker (from the content player in SSAI mode) to IMA for ad tracking. Picks the ID3 TXXX user text (falling back to the first frame / message payload). No-op when no text is present.
Replace ad-tag parameters on the active stream session. No-op if not initialized.
Install the sink for IMA ad-progress events; replaces any earlier one.
Open a full-service IMA DAI live-stream session and suspend until IMA hands back the stitched stream URL to play on the content player.
Main thread for the same reason as initialize. IMA 3.35's live-stream request takes the asset key and api key only — the network code the manifest carries alongside them is not part of this request.
Initialize a fresh IMA pod-serving session and suspend until the stream id is available (or the request errors). Always resets any prior session.
Runs on the MAIN thread: IMA builds Handlers internally while creating the loader and display container, so on a thread with no Looper it throws "Attempt to read from field android.os.Looper.mQueue on a null object reference" and the session never opens — after which every GAM pod asset fails instantly and the break collapses in milliseconds. This is the counterpart of the Swift twin's @MainActor.
The native Android agent happened to drive the SDK on Dispatchers.Main and never hit it; the React Native bridge used Dispatchers.Default and hit it on every session.
Whether a stream session has been initialized with a valid streamId.
Forward timed metadata (HLS ID3 TXXX text) from the ad player to IMA.
Forward an in-stream timed-metadata marker (from the content player in SSAI mode) to IMA for ad tracking. Picks the ID3 TXXX user text (falling back to the first frame / message payload). No-op when no text is present.
Replace ad-tag parameters on the active stream session. No-op if not initialized.
Reset session state before starting a new session.
Main thread, for the same reason as initialize: streamManager.destroy() tears down IMA's own views and handlers. Kept SYNCHRONOUS rather than posted, because initialize calls it immediately before creating the replacement loader — a posted reset would run after that and null out the NEW session.
Install the sink for IMA ad-progress events; replaces any earlier one.
Release all IMA + ad-player resources.
Real IMA client-side VastAdManager. Drives AdsLoader.requestAds with the VAST tag URL, renders via an AdVideoPlayer backed by the SDK's ad ExoPlayer, and maps IMA AdEvent/AdErrorEvent to VastAdEventCallbacks
the suspending completion.
Request, render, and play adTagUrl; suspends until complete, throws on error.
The tag currently warmed and waiting, or null.
Phase 1 of the two-phase path: fetch, parse and init() the ad for adTagUrl WITHOUT starting it. Suspends until IMA has an AdsManager ready to play.
Phase 2: start the ad warmed by preloadVast. Suspends until complete, like playVast, and throws if nothing is warmed.
Request, render, and play adTagUrl; suspends until complete, throws on error.
Phase 1 of the two-phase path: fetch, parse and init() the ad for adTagUrl WITHOUT starting it. Suspends until IMA has an AdsManager ready to play.
This is what takes the ad request off the critical path. A cold playVast does the whole IMA round-trip at break start, which measured 1675ms p50 (gam-csai) and 2436ms (vast) into the break on Android device runs, against 22-43ms on web, which has always preloaded. Content is silenced the moment the break begins, so that gap is heard as silence over still-moving content.
NO muted parameter, unlike the web signature. Web's IMA owns the video element, so it must be told the intended volume before it creates the AdsManager. Android's IMA renders through the SDK's OWN VideoAdPlayer on the ad ExoPlayer, whose mute state the renderer already applies at break start — a volume argument here would do nothing, and AdsManager exposes no volume control to honour it with.
The tag currently warmed and waiting, or null.
The caller compares it against the tag it is about to play: a warm for a DIFFERENT tag is useless, and starting it would play the wrong ad.
Phase 2: start the ad warmed by preloadVast. Suspends until complete, like playVast, and throws if nothing is warmed.
AdRenderer.abortBreak: ends the in-progress break now and resumes content at the break start plus resumeOffsetSec.
AdRenderer.destroy: restores content state, releases the ad player and removes the overlay views.
AdRenderer.endGamSession: resets the IMA stream manager and drops the session asset parameters.
AdRenderer.endSteeredSsaiSession: resets the IMA stream manager of a steered ssai session.
AdRenderer.forwardSsaiTimedMetadata: hands the content cue to the IMA stream manager.
AdRenderer.hidePauseAd: fades the pause ad out and releases its resources.
Overlay AdRenderer for Android: plays break assets on a dedicated ad ExoPlayer in a PlayerView above the integrator's content surface. Event ORDER comes from the portable AdBreakSequencer; this class only performs side effects and reports outcomes back.
The responsibilities live in extension files of the same package (Overlay*.kt); this file holds the state, the public API and the break entry points. All ExoPlayer interaction is marshalled onto Dispatchers.Main.
AdRenderer.abortBreak: ends the in-progress break now and resumes content at the break start plus resumeOffsetSec.
AdRenderer.destroy: restores content state, releases the ad player and removes the overlay views.
AdRenderer.endGamSession: resets the IMA stream manager and drops the session asset parameters.
AdRenderer.endSteeredSsaiSession: resets the IMA stream manager of a steered ssai session.
AdRenderer.forwardSsaiTimedMetadata: hands the content cue to the IMA stream manager.
AdRenderer.hidePauseAd: fades the pause ad out and releases its resources.
AdRenderer.initialize: builds the ad PlayerView, the image and companion views and the GAM stream manager inside overlayContainer.
AdRenderer.isAdPlaying: true from break begin to break end.
Not gated on a GamConfig being supplied, only on the explicit opt-out.
An lshape_content break in PiP is active but shows no ad; isAdPlaying stays true.
AdRenderer.playBreak: plays the selected variant of breakInfo asset by asset and suspends until the break ends or is cut.
AdRenderer.preload: warms the media of the variant that will play, subject to the preload mode.
AdRenderer.prepareAdRequest: awaits the installed preparer, if any.
AdRenderer.revealPauseAdResume: shows the resume control of the mounted pause ad.
AdRenderer.setAdClickHandler: installs the handler invoked when the viewer taps the ad surface.
AdRenderer.setAdPreloadMode: decides whether preload may warm media in the ad player.
AdRenderer.setAdRequestPreparer: installs the hook awaited before every ad request.
AdRenderer.setAudio: applies the unified mute and volume to the ad player and any pause-ad video.
AdRenderer.setBreakCutSafetyMargin: overrides the constructor adBreakCutSafetyMarginSec.
AdRenderer.setBreakResumePolicy: sets the insertion type, timebase and continue-content option that decide where content resumes.
AdRenderer.setChainResolver: installs the resolver used to soft-end into a chained break.
AdRenderer.setDiagnoseHandler: installs the sink for renderer diagnostics.
AdRenderer.setDoubleBoxAudio: selects which side stays audible in a double break.
AdRenderer.setGamEventCallbacks: installs the quartile sink for GAM and VAST ads.
AdRenderer.setManifestAssetParameters: installs the manifest session layer and pushes a change to a live IMA session.
AdRenderer.setPauseAdCreativeEndedCallback: installs the callback for a pause-ad video that ended or failed.
AdRenderer.setPictureInPicture: re-lays out a break in flight as single when picture-in-picture starts.
AdRenderer.setPictureInPictureChangeHandler: starts watching the host Activity for picture-in-picture changes; null stops watching.
AdRenderer.setSessionAssetParameterMacros: installs the customer macros for the session.
AdRenderer.setSessionAssetParameters: installs the session layer of the asset parameters.
AdRenderer.setTransitionDurationMs: overrides the constructor transitionMs; 0 cuts without a fade.
AdRenderer.setTransitionPhaseReporter: installs the break-transition checkpoint reporter used in debug mode.
AdRenderer.showPauseAd: resolves the pause-ad creative and fades it in over the paused content.
AdRenderer.startGamSession: opens the IMA pod-serving stream for identity and installs the session asset parameters.
Unlike startGamSession the ads arrive inside the stitched stream; no pod is played.
AdRenderer.updateAssetParameterMacros: merges the customer macros and pushes them to a live IMA session.
AdRenderer.updateAssetParameters: replaces the live-update layer and pushes the merged parameters to IMA.
PiP narrows the playable-format set to single + the suppressed lshape_content.
AdRenderer.initialize: builds the ad PlayerView, the image and companion views and the GAM stream manager inside overlayContainer.
AdRenderer.isAdPlaying: true from break begin to break end.
Not gated on a GamConfig being supplied, only on the explicit opt-out.
An lshape_content break in PiP is active but shows no ad; isAdPlaying stays true.
AdRenderer.playBreak: plays the selected variant of breakInfo asset by asset and suspends until the break ends or is cut.
AdRenderer.preload: warms the media of the variant that will play, subject to the preload mode.
AdRenderer.prepareAdRequest: awaits the installed preparer, if any.
AdRenderer.revealPauseAdResume: shows the resume control of the mounted pause ad.
AdRenderer.setAdClickHandler: installs the handler invoked when the viewer taps the ad surface.
AdRenderer.setAdPreloadMode: decides whether preload may warm media in the ad player.
AdRenderer.setAdRequestPreparer: installs the hook awaited before every ad request.
AdRenderer.setAudio: applies the unified mute and volume to the ad player and any pause-ad video.
AdRenderer.setBreakCutSafetyMargin: overrides the constructor adBreakCutSafetyMarginSec.
AdRenderer.setBreakResumePolicy: sets the insertion type, timebase and continue-content option that decide where content resumes.
AdRenderer.setChainResolver: installs the resolver used to soft-end into a chained break.
AdRenderer.setDiagnoseHandler: installs the sink for renderer diagnostics.
AdRenderer.setDoubleBoxAudio: selects which side stays audible in a double break.
AdRenderer.setGamEventCallbacks: installs the quartile sink for GAM and VAST ads.
AdRenderer.setManifestAssetParameters: installs the manifest session layer and pushes a change to a live IMA session.
AdRenderer.setPauseAdCreativeEndedCallback: installs the callback for a pause-ad video that ended or failed.
AdRenderer.setPictureInPictureChangeHandler: starts watching the host Activity for picture-in-picture changes; null stops watching.
AdRenderer.setPictureInPicture: re-lays out a break in flight as single when picture-in-picture starts.
AdRenderer.setSessionAssetParameterMacros: installs the customer macros for the session.
AdRenderer.setSessionAssetParameters: installs the session layer of the asset parameters.
AdRenderer.setTransitionDurationMs: overrides the constructor transitionMs; 0 cuts without a fade.
AdRenderer.setTransitionPhaseReporter: installs the break-transition checkpoint reporter used in debug mode.
AdRenderer.showPauseAd: resolves the pause-ad creative and fades it in over the paused content.
Reuses the break-cut path so the sequencer emits a balanced adend + adbreakend.
AdRenderer.startGamSession: opens the IMA pod-serving stream for identity and installs the session asset parameters.
Unlike startGamSession the ads arrive inside the stitched stream; no pod is played.
AdRenderer.updateAssetParameterMacros: merges the customer macros and pushes them to a live IMA session.
AdRenderer.updateAssetParameters: replaces the live-update layer and pushes the merged parameters to IMA.
PiP narrows the playable-format set to single + the suppressed lshape_content.
Ad-progress callbacks fired during a single VAST (CSAI) ad — the Kotlin mirror of the web VastAdManager callbacks. Quartiles map onto the SDK's existing GAM quartile event stream in OverlayAdRenderer.
The VAST ad reached 25%.
The VAST ad reached 50%.
Real ad playback progress during the VAST ad, in seconds (PLAYG-281). Fired on the same 250 ms cadence the IMA AdVideoPlayer already polls the ad ExoPlayer at. OverlayAdRenderer forwards it to the SDK's onAdTimeUpdate so the break countdown ticks from actual playback. Mirrors the web VastAdManager onAdProgress (IMA AD_PROGRESS).
podPosition is the 1-based position IMA reports for the ad within its pod (adPodInfo.adPosition, which carries the VAST sequence for pods); null when IMA reports none.
The VAST ad reached 75%.
The VAST ad reached 25%.
The VAST ad reached 50%.
Real ad playback progress during the VAST ad, in seconds (PLAYG-281). Fired on the same 250 ms cadence the IMA AdVideoPlayer already polls the ad ExoPlayer at. OverlayAdRenderer forwards it to the SDK's onAdTimeUpdate so the break countdown ticks from actual playback. Mirrors the web VastAdManager onAdProgress (IMA AD_PROGRESS).
podPosition is the 1-based position IMA reports for the ad within its pod (adPodInfo.adPosition, which carries the VAST sequence for pods); null when IMA reports none.
The VAST ad reached 75%.
Release all IMA + ad-player resources.
Plays a single VAST ad tag client-side (CSAI) — the Kotlin counterpart of the web @dolby-optiview/ads-sdk-core VastAdManager. This is the client-side IMA surface (AdsLoader/AdsManager/AdDisplayContainer + a VideoAdPlayer), distinct from the DAI pod-serving GamStreamManager: here IMA fetches/parses the VAST document and the SDK's ad ExoPlayer renders the creative.
Modeled behind an interface so OverlayAdRenderer can be unit-tested with a fake (the IMA SDK has no headless mode; the real device path is exercised by native e2e). playVast suspends until the ad completes (ALL_ADS_COMPLETED) and throws VendorAdException (carrying IMA's error code) on an IMA error, or VastAdException for SDK-side misuse.
Request, render, and play adTagUrl; suspends until complete, throws on error.
The tag currently warmed and waiting, or null.
Phase 1 of the two-phase path: fetch, parse and init() the ad for adTagUrl WITHOUT starting it. Suspends until IMA has an AdsManager ready to play.
Phase 2: start the ad warmed by preloadVast. Suspends until complete, like playVast, and throws if nothing is warmed.
Request, render, and play adTagUrl; suspends until complete, throws on error.
Phase 1 of the two-phase path: fetch, parse and init() the ad for adTagUrl WITHOUT starting it. Suspends until IMA has an AdsManager ready to play.
This is what takes the ad request off the critical path. A cold playVast does the whole IMA round-trip at break start, which measured 1675ms p50 (gam-csai) and 2436ms (vast) into the break on Android device runs, against 22-43ms on web, which has always preloaded. Content is silenced the moment the break begins, so that gap is heard as silence over still-moving content.
NO muted parameter, unlike the web signature. Web's IMA owns the video element, so it must be told the intended volume before it creates the AdsManager. Android's IMA renders through the SDK's OWN VideoAdPlayer on the ad ExoPlayer, whose mute state the renderer already applies at break start — a volume argument here would do nothing, and AdsManager exposes no volume control to honour it with.
The tag currently warmed and waiting, or null.
The caller compares it against the tag it is about to play: a warm for a DIFFERENT tag is useless, and starting it would play the wrong ad.
Phase 2: start the ad warmed by preloadVast. Suspends until complete, like playVast, and throws if nothing is warmed.
Classify the host device into a DeviceType for per-URI asset targeting (see resolveTargetedUri).
This is Android platform glue, not portable brain behaviour, so it has no cross-language conformance fixture — deliberately mirroring the web detectDeviceType, which sniffs a User-Agent string and is likewise excluded. Android can do far better than a UA heuristic: the system tells us directly whether we are on a TV, and the smallest-width qualifier is the same signal the resource system uses to pick layout-sw600dp.
Order matters: TV first, because an Android TV device also reports a large smallest-width and would otherwise be classified as a tablet.
DeviceType.DESKTOP is never returned — it has no Android meaning. An asset array targeting only desktop therefore falls through to its untargeted default here, which is the intended behaviour.
The Media3 player adapter, the overlay ad renderer with its scaling and audio focus options, the GAM stream manager and its configuration, the VAST ad manager, and the device type detection.
Thrown to represent an ad asset that failed to play (surfaced via aderror).
The renderer's handle on audio focus for ad playback. request/abandon bracket a break; focus transitions while held arrive via AdAudioFocusCallbacks.
What the renderer does when the system moves audio focus around during a break. Split from the platform calls so unit tests can drive focus transitions directly.
Outcome of an AdAudioFocus.request.
Platform AdAudioFocus over AudioManager.
Media3/ExoPlayer implementation of the portable PlayerAdapter (P4b-2).
Callbacks for IMA ad-progress events (mirrors the web GamAdEventCallbacks).
Configuration for a full-service IMA DAI live-stream session (ADS-326 steered ssai): the ads are stitched by Google and the SDK plays the single returned stream, so this carries the DAI assetKey rather than the pod-serving customAssetKey.
Thrown when the IMA DAI session fails to initialize.
Manages a Google IMA DAI SDK pod-serving session on Android — the Kotlin mirror of the web GamStreamManager. Initializes an IMA StreamManager via a PodStreamRequest, exposes the resulting streamId for pod-manifest URL construction (delegated to the portable buildGamPodUrl), and forwards ad progress/quartile events.
Real IMA client-side VastAdManager. Drives AdsLoader.requestAds with the VAST tag URL, renders via an AdVideoPlayer backed by the SDK's ad ExoPlayer, and maps IMA AdEvent/AdErrorEvent to VastAdEventCallbacks
Overlay AdRenderer for Android: plays break assets on a dedicated ad ExoPlayer in a PlayerView above the integrator's content surface. Event ORDER comes from the portable AdBreakSequencer; this class only performs side effects and reports outcomes back.
Ad-progress callbacks fired during a single VAST (CSAI) ad — the Kotlin mirror of the web VastAdManager callbacks. Quartiles map onto the SDK's existing GAM quartile event stream in OverlayAdRenderer.
Thrown when the IMA client-side (CSAI) SDK fails to load or play a VAST ad.
Plays a single VAST ad tag client-side (CSAI) — the Kotlin counterpart of the web @dolby-optiview/ads-sdk-core VastAdManager. This is the client-side IMA surface (AdsLoader/AdsManager/AdDisplayContainer + a VideoAdPlayer), distinct from the DAI pod-serving GamStreamManager: here IMA fetches/parses the VAST document and the SDK's ad ExoPlayer renders the creative.
Classify the host device into a DeviceType for per-URI asset targeting (see resolveTargetedUri).
The Android runtime of the OptiView Ads SDK, and the artifact an app depends on: ExoPlayerAdapter (the PlayerAdapter for Media3 / ExoPlayer), OverlayAdRenderer (ad playback in an overlay above the content player, including pause ads), GamStreamManager (Google Ad Manager pod serving through the IMA SDK) and VastAdManager (client-side VAST playout). Depends on ads-sdk and ads-sdk-core.
IMA creative id for an ad of a GAM pod (PLAYG-362); null otherwise.
Declared format of the break's selected variant (PLAYG-182).
An individual ad starts playing. A GAM pod reports one adbegin per ad it was filled with.
IMA creative id for an ad of a GAM pod (PLAYG-362); null otherwise.
Declared format of the break's selected variant (PLAYG-182).
1-based position of the ad within its pod, as the ad system reports it at runtime (IMA adPodInfo.adPosition / VAST sequence). Null when the ad system reports none — static assets never have one.
Which event this is.
1-based position of the ad within its pod, as the ad system reports it at runtime (IMA adPodInfo.adPosition / VAST sequence). Null when the ad system reports none — static assets never have one.
Which event this is.
Seconds already elapsed since the break's start when this viewer joined it. Zero only for a break caught at its exact start.
Declared format of the break's selected variant (PLAYG-182).
An ad break starts and content is paused (or, for lshape_content and overlay breaks, keeps playing).
Seconds already elapsed since the break's start when this viewer joined it. Zero only for a break caught at its exact start.
Declared format of the break's selected variant (PLAYG-182).
Effective duration, in seconds, the break is presented for. ALWAYS reported: a viewer can be part-way into a break without the join being classified as a tune-in, because inside the start tolerance the flag is false while several seconds may already have passed.
Present when the viewer joined a break already in progress, absent for an on-time trigger. Its presence is the join CLASSIFICATION; the durations below are the measurement and are always correct.
Which event this is.
Effective duration, in seconds, the break is presented for. ALWAYS reported: a viewer can be part-way into a break without the join being classified as a tune-in, because inside the start tolerance the flag is false while several seconds may already have passed.
Present when the viewer joined a break already in progress, absent for an on-time trigger. Its presence is the join CLASSIFICATION; the durations below are the measurement and are always correct.
Which event this is.
Declared format of the break's selected variant (PLAYG-182).
An ad break ends and content resumes.
Which event this is.
A break is currently playing.
No break is upcoming or active.
A break is scheduled in the future, including pre-break warnings.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Lifecycle phase reported by AdBreakStatus. Mirrors the TS AdBreakPhase.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Event emitted when the status of the current or upcoming ad break changes. Carries a complete AdBreakStatus snapshot. Mirrors the TS AdBreakStatusEvent.
The complete status at the time of the event.
Which event this is.
Number of ads remaining including the currently playing one.
Estimated seconds remaining in the currently active break, when it can be derived from playback progress. null when not yet known (e.g. a backdrop break with no per-ad timeupdate).
The break this status describes; null when phase is AdBreakPhase.IDLE.
Declared format of the break's selected variant, when known.
Playback-gated snapshot of an ad break for UI countdowns — the Kotlin mirror of the web AdBreakStatus (packages/core/src/types/Events.ts). The SDK owns the timebase and the player-gated ticking flag; the application renders the badge/overlay. Emitted on the AdBreakStatusEvent and returned by OptiViewAds.getAdBreakStatus.
Number of ads remaining including the currently playing one.
The break this status describes; null when phase is AdBreakPhase.IDLE.
Estimated seconds remaining in the currently active break, when it can be derived from playback progress. null when not yet known (e.g. a backdrop break with no per-ad timeupdate).
Declared format of the break's selected variant, when known.
Current lifecycle phase of the ad break.
Seconds until the break starts. Populated for upcoming warnings — the live countdown value at the moment the warning fired.
When this status was emitted because of a configured pre-break warning, the configured warning second that was crossed.
Current lifecycle phase of the ad break.
Seconds until the break starts. Populated for upcoming warnings — the live countdown value at the moment the warning fired.
When this status was emitted because of a configured pre-break warning, the configured warning second that was crossed.
Delivery mode in effect after the switch.
A polled manifest described a different ads channel and the SDK re-aligned its ad setup to it while the session and content playback continued. Fires once per switch, after a break in progress has finished and the new manifest is applied.
Delivery mode in effect after the switch.
The manifest URL of the session.
The channelId before the switch; null when the manifest had none.
Delivery mode in effect before the switch.
What changed between the two manifests.
Which event this is.
The manifest URL of the session.
The channelId before the switch; null when the manifest had none.
Delivery mode in effect before the switch.
What changed between the two manifests.
Which event this is.
The asset's declared click-through URL, when the manifest supplies one.
Declared format of the break's selected variant (PLAYG-182).
The viewer clicked/tapped the ad on screen (or the application called OptiViewAds.clickAd programmatically) — the Kotlin mirror of the iOS/web adclick event. Carries the asset's declared interaction.clickThrough URL when the manifest supplies one; the SDK deliberately does NOT open it — that is the application's decision.
The asset's declared click-through URL, when the manifest supplies one.
Declared format of the break's selected variant (PLAYG-182).
Which event this is.
Which event this is.
The IMA creative id.
The creative identity IMA reports for an ad of a GAM pod (PLAYG-361/362). Absent for every other asset kind, where the manifest asset already identifies the ad.
The IMA creative id.
1-based position of the ad within its pod, as the ad system reports it at runtime (IMA adPodInfo.adPosition / VAST sequence). Null when the ad system reports none — static assets never have one.
1-based position of the ad within its pod, as the ad system reports it at runtime (IMA adPodInfo.adPosition / VAST sequence). Null when the ad system reports none — static assets never have one.
IMA creative id for an ad of a GAM pod (PLAYG-362); null otherwise.
Declared format of the break's selected variant (PLAYG-182).
An individual ad finishes.
IMA creative id for an ad of a GAM pod (PLAYG-362); null otherwise.
Declared format of the break's selected variant (PLAYG-182).
Which event this is.
Which event this is.
Declared format of the break's selected variant; null for content errors (PLAYG-182).
Playback failed. Emitted for both the content player and the SDK's ad player; source tells them apart. An ad error is not fatal: the SDK skips the asset and continues the break or resumes content.
Declared format of the break's selected variant; null for content errors (PLAYG-182).
Which player failed.
Which event this is.
Which player failed.
Which event this is.
Declared format of the break's selected variant (PLAYG-182).
An ad reached 25% completion.
Which event this is.
Overlay when possible, shared element when the platform requires it.
Let the SDK pick per device.
Ads play in the SDK's own player stacked above the content player.
Ads play in the content player itself.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Ad insertion strategy. auto resolves per device (iPhone/iPod → adaptive or shared-element; otherwise overlay). On Android this resolves to OVERLAY.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Declared format of the break's selected variant (PLAYG-182).
An ad reached 50% completion.
Which event this is.
Let the SDK pick from the adapter's supportsParallelBuffering hint.
Buffer the ad in a second decoder while content keeps playing.
Prepare the ad without buffering ahead; for devices with a single decoder.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Ad preload strategy. auto resolves at runtime (decoder-limited devices → SINGLE_DECODER, otherwise PARALLEL).
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
End the in-progress break NOW because it was REMOVED from a polled manifest — the manifest spec's "early return". Same balanced cut path as skipBreak (adend + adbreakend), with two differences the renderer must honor: content resumes at break.start + resumeOffsetSec (the seconds the break already played — overriding the DAR/DAI defaults and forcing the seek in replacement mode), and a chained successor must NOT begin now (the scheduler triggers it at its own start time). No-op when no break is playing. Default no-op so fakes need not override.
Release renderer resources.
Tear down the active GAM/IMA session (on session end).
Tear down the active manifest-steered ssai session (on session end).
Forward an in-stream timed-metadata cue from the CONTENT player to IMA so a steered ssai session fires its ad-tracking beacons.
Hide the pause ad (on resume or duration cap), fading it out. Default no-op.
The ad-rendering boundary — the Kotlin counterpart of the web AdPlayerController. The orchestrator (OptiViewAds) stays player-agnostic and delegates everything that touches a media surface, an overlay, or GAM/IMA to an AdRenderer. The Android runtime renderer (Media3 ad player + overlay + IMA DAI) implements this in P4b; tests and the conformance driver supply a fake.
Intra-break ad-event ordering itself is decided by the portable AdBreakSequencer in :ads-sdk-core; the renderer is responsible only for actually loading/playing assets and reporting back through BreakPlaybackCallbacks in that sequencer-defined order.
End the in-progress break NOW because it was REMOVED from a polled manifest — the manifest spec's "early return". Same balanced cut path as skipBreak (adend + adbreakend), with two differences the renderer must honor: content resumes at break.start + resumeOffsetSec (the seconds the break already played — overriding the DAR/DAI defaults and forcing the seek in replacement mode), and a chained successor must NOT begin now (the scheduler triggers it at its own start time). No-op when no break is playing. Default no-op so fakes need not override.
Tear down the active GAM/IMA session (on session end).
Tear down the active manifest-steered ssai session (on session end).
Forward an in-stream timed-metadata cue from the CONTENT player to IMA so a steered ssai session fires its ad-tracking beacons.
Hide the pause ad (on resume or duration cap), fading it out. Default no-op.
One-time overlay/surface setup, called once at construction.
Whether an ad is currently on screen (used for overlap suppression / control gating).
Whether a GAM/IMA pod-serving session is configured for this renderer.
Whether the surface currently shows AD content, as opposed to the main content.
Play a whole break, reporting progress via callbacks; suspends until the break ends. effectiveDurationSec, when non-null, is the remaining duration to present a tune-in (join-in-progress) break for — used for the GAM pod URL and any backdrop hold — instead of the full break.duration.
Await the installed ad-request preparer (see setAdRequestPreparer) outside an ad request, for a caller about to push parameters to the live IMA session. No-op without a preparer.
Show the resume/close controls of the mounted pause ad (the viewer may resume content). Default no-op.
Install the handler the renderer invokes when the viewer taps/clicks the ad surface during a break. The orchestrator routes it into the public adclick event. Default no-op so renderers/fakes without a click surface need not override.
Set the resolved ad-preload mode for the session.
Install a hook the renderer awaits before it builds an ad request (VAST tag URL or GAM parameters), so a host whose macro values live outside this thread — the React Native bridge, which asks JS for them — can refresh them first. Null (the default) skips the wait.
Set the safety margin (seconds) added to a break's effective duration before the break-cut timer hard-cuts back to content.
Set the per-session break resume policy: the ad insertion type (DAR/DAI) and the manifest timebase. Drives the content resume point computed when a break that paused content ends. Mirrors the web AdPlayerController.setBreakResumePolicy. Default no-op so renderers and fakes that never resume content need not override.
Install the resolver the renderer calls to soft-end into the break chained after the current one; null disables chaining.
Install the sink the renderer reports structured diagnostics to (e.g. VAST CSAI guard/error codes). Mirrors the web AdPlayerController.setDiagnoseHandler. Default no-op so renderers/fakes that emit no diagnostics need not override.
Which side keeps audio during a double-format break.
Install the GAM quartile callbacks the renderer fires during ad playback.
Install the manifest session layer (vendorConfiguration[gam].sgai[0].assetParameters, or ssai[0].assetParameters for a stitched stream). Called at session start and on every manifest poll; a changed layer is pushed to the live IMA session without recreating it.
Invoked with the break id when a video pause-ad creative ends or cannot play. null detaches. Default no-op.
Tell the renderer whether the content player is currently in picture-in-picture.
Install the sink the renderer reports picture-in-picture transitions UP through.
Install the customer asset-parameter macros (SessionConfig.assetParameterMacros) for the session about to start. Each callback resolves the $-prefixed name it is keyed by; a null result leaves the name unresolved.
Install the session layer of the asset parameters (SessionConfig.assetParameters) for the session about to start. Independent of startGamSession because VAST assets consume the same layers without a GAM session.
Set how long the renderer animates the picture change at the edges of a break, in milliseconds; 0 means cut with no animation.
Inject a reporter for sub-phase checkpoints inside a break transition, used to attribute transition cost (PLAYG-344 — mirror of the web AdPlayerController.setTransitionPhaseReporter). Pass null to disable, which is the default — the SDK only wires this in debug mode, so production DA-BREAK-TRANSITION reports keep their existing shape. Default no-op.
Show a full-screen pause ad over the (paused) content, fading it in. The orchestrator's com.dolby.optiview.ads.core.PauseAdController decides when this is called; the renderer resolves the image source (static URL or vast CompanionAds), fires any creativeView impressions, and draws the overlay with a resume affordance. Default no-op so non-overlay renderers/fakes need not override. com.dolby.optiview.ads.core.PauseAdResolution carries the break, image asset, and source.
Cut the in-progress break short NOW (viewer skip). The renderer must end the break through its normal cut path so the sequencer still emits the balanced adend + adbreakend steps — exactly like the break-cut timer. No-op when no break is playing. The orchestrator (OptiViewAds.skipAd) owns the skip POLICY (controls.skipOffset gating); the renderer only performs the cut. Default no-op so renderers/fakes without a skip surface need not override.
Initialize the GAM/IMA stream session for identity; suspends until ready.
Open a full-service IMA DAI session for the manifest-steered ssai stream vendor describes and return the stitched stream URL to play on the CONTENT player (ADS-326). Suspends until IMA returns the URL.
Merge customer macros by name; null removes a name so the built-in applies again. The update is pushed to the live IMA session when one is active.
Replace the live-update layer of the asset parameters for the active session (no re-init).
The variant-selection context this renderer plays breaks under: the detected device class plus the CONTEXTUAL playable-format set (narrowed while content is in picture-in-picture). The orchestrator feeds it into the portable selection both for its pre-adbreakbegin gate and for the public events' declared format. Defaults to "unknown device, every renderable format" so fakes and tests keep compiling.
One-time overlay/surface setup, called once at construction.
Whether an ad is currently on screen (used for overlap suppression / control gating).
Whether a GAM/IMA pod-serving session is configured for this renderer.
Whether the surface currently shows AD content, as opposed to the main content.
Almost always the same answer as isAdPlaying, and defaults to it — but not always: an lshape_content break in picture-in-picture is active (so controls stay gated and a second break must not start) while showing nothing but the main content, because its backdrop is suppressed at that size. Drives OptiViewAds.getPresentationState.
Play a whole break, reporting progress via callbacks; suspends until the break ends. effectiveDurationSec, when non-null, is the remaining duration to present a tune-in (join-in-progress) break for — used for the GAM pod URL and any backdrop hold — instead of the full break.duration.
Await the installed ad-request preparer (see setAdRequestPreparer) outside an ad request, for a caller about to push parameters to the live IMA session. No-op without a preparer.
Show the resume/close controls of the mounted pause ad (the viewer may resume content). Default no-op.
Install the handler the renderer invokes when the viewer taps/clicks the ad surface during a break. The orchestrator routes it into the public adclick event. Default no-op so renderers/fakes without a click surface need not override.
Set the resolved ad-preload mode for the session.
com.dolby.optiview.ads.core.PreloadMode.PARALLEL permits warming an upcoming ad's media while content is still playing — which means holding a second video decoder. com.dolby.optiview.ads.core.PreloadMode.SINGLE_DECODER forbids it, because on constrained hardware (older TVs, some FireTV models) a second decoder starves the content player instead of speeding the ad up.
OptiViewAds already resolves this from OptiViewAdsConfig.adPreload via the portable resolvePreloadMode, but until this hook existed the result was only reported in the redacted ConfigSummary and never acted on — so parallel vs single-decoder had no behavioural effect whatsoever. Default no-op, like the other optional hooks.
Install a hook the renderer awaits before it builds an ad request (VAST tag URL or GAM parameters), so a host whose macro values live outside this thread — the React Native bridge, which asks JS for them — can refresh them first. Null (the default) skips the wait.
Apply the session's unified audio state to everything the renderer owns that can make sound: the ad player (which on Android renders IMA VAST creatives too) and any pause-ad video.
The renderer must also RE-APPLY this whenever it starts a new ad, so a break inherits the state rather than starting at the player's default — otherwise muting during content would be undone the moment an ad began. Default no-op.
Set the safety margin (seconds) added to a break's effective duration before the break-cut timer hard-cuts back to content.
On Android the integrator constructs the renderer, so it can carry its own constructor default for this. Pushing OptiViewAdsConfig.adBreakCutSafetyMarginSec through here keeps the one config object authoritative — otherwise setting it only on the config silently had no effect. Default no-op.
Set the per-session break resume policy: the ad insertion type (DAR/DAI) and the manifest timebase. Drives the content resume point computed when a break that paused content ends. Mirrors the web AdPlayerController.setBreakResumePolicy. Default no-op so renderers and fakes that never resume content need not override.
Install the resolver the renderer calls to soft-end into the break chained after the current one; null disables chaining.
Install the sink the renderer reports structured diagnostics to (e.g. VAST CSAI guard/error codes). Mirrors the web AdPlayerController.setDiagnoseHandler. Default no-op so renderers/fakes that emit no diagnostics need not override.
Which side keeps audio during a double-format break.
Default-implemented, like setAdPreloadMode, so a custom renderer that does not composite two boxes at once is unaffected.
Install the GAM quartile callbacks the renderer fires during ad playback.
Install the manifest session layer (vendorConfiguration[gam].sgai[0].assetParameters, or ssai[0].assetParameters for a stitched stream). Called at session start and on every manifest poll; a changed layer is pushed to the live IMA session without recreating it.
Invoked with the break id when a video pause-ad creative ends or cannot play. null detaches. Default no-op.
Install the sink the renderer reports picture-in-picture transitions UP through.
The return path for setPictureInPicture. A renderer that can observe the host's picture-in-picture state itself — OverlayAdRenderer in ads-sdk-runtime watches the Activity it can reach from its own Context — reports changes here, so the orchestrator learns about a transition the VIEWER started (the system PiP button, or the swipe-home gesture on an auto-PiP Activity) without the host app wiring anything.
That is the whole point: this SDK is an add-on, and an integrator should not have to forward Activity.onPictureInPictureModeChanged for break layout to be correct. Web and iOS have always detected it themselves; Android was the outlier.
The orchestrator's OptiViewAds.setPictureInPicture is idempotent, so a host that ALSO forwards the callback costs nothing — whichever path observes the change first wins and the other is a no-op. Default no-op, like the other optional hooks.
Tell the renderer whether the content player is currently in picture-in-picture.
Forwarded from OptiViewAds.setPictureInPicture. While active, every break plays as com.dolby.optiview.ads.core.BreakFormat.SINGLE — see com.dolby.optiview.ads.core.effectiveBreakFormat. Default no-op: a renderer that never shares a surface with PiP (or a fake) need not care.
Install the customer asset-parameter macros (SessionConfig.assetParameterMacros) for the session about to start. Each callback resolves the $-prefixed name it is keyed by; a null result leaves the name unresolved.
Install the session layer of the asset parameters (SessionConfig.assetParameters) for the session about to start. Independent of startGamSession because VAST assets consume the same layers without a GAM session.
Set how long the renderer animates the picture change at the edges of a break, in milliseconds; 0 means cut with no animation.
Pushed from OptiViewAdsConfig.transition so the host's choice reaches a renderer it constructed itself; the renderer's own constructor parameter stays the fallback for anything built before this hook existed. Default no-op, like the other optional hooks.
Inject a reporter for sub-phase checkpoints inside a break transition, used to attribute transition cost (PLAYG-344 — mirror of the web AdPlayerController.setTransitionPhaseReporter). Pass null to disable, which is the default — the SDK only wires this in debug mode, so production DA-BREAK-TRANSITION reports keep their existing shape. Default no-op.
Show a full-screen pause ad over the (paused) content, fading it in. The orchestrator's com.dolby.optiview.ads.core.PauseAdController decides when this is called; the renderer resolves the image source (static URL or vast CompanionAds), fires any creativeView impressions, and draws the overlay with a resume affordance. Default no-op so non-overlay renderers/fakes need not override. com.dolby.optiview.ads.core.PauseAdResolution carries the break, image asset, and source.
Cut the in-progress break short NOW (viewer skip). The renderer must end the break through its normal cut path so the sequencer still emits the balanced adend + adbreakend steps — exactly like the break-cut timer. No-op when no break is playing. The orchestrator (OptiViewAds.skipAd) owns the skip POLICY (controls.skipOffset gating); the renderer only performs the cut. Default no-op so renderers/fakes without a skip surface need not override.
Initialize the GAM/IMA stream session for identity; suspends until ready.
identity comes from the break manifest's root vendorConfiguration, so this can only be called once the manifest has been fetched.
assetParameters is the SESSION layer only — the manifest's per-asset layer is applied later by the renderer, since which asset will play is not knowable here.
Open a full-service IMA DAI session for the manifest-steered ssai stream vendor describes and return the stitched stream URL to play on the CONTENT player (ADS-326). Suspends until IMA returns the URL.
Distinct from startGamSession, which opens a pod-serving session for ads the SDK stitches and plays itself: here the ads are already in the stream.
The default throws, so a renderer without an IMA DAI integration reports the gap through DA-SSAI-SESSION-FAILED instead of appearing to steer into ssai.
Merge customer macros by name; null removes a name so the built-in applies again. The update is pushed to the live IMA session when one is active.
Replace the live-update layer of the asset parameters for the active session (no re-init).
The variant-selection context this renderer plays breaks under: the detected device class plus the CONTEXTUAL playable-format set (narrowed while content is in picture-in-picture). The orchestrator feeds it into the portable selection both for its pre-adbreakbegin gate and for the public events' declared format. Defaults to "unknown device, every renderable format" so fakes and tests keep compiling.
Declared format of the break's selected variant (PLAYG-182).
An ad reached 75% completion.
Which event this is.
Position within the ad, in seconds.
Declared format of the break's selected variant (PLAYG-182).
Ad playback progressed; fires on each time update of the ad player (about 4 Hz). For a GAM pod the times describe the whole pod, not the ad on screen.
Position within the ad, in seconds.
Declared format of the break's selected variant (PLAYG-182).
Which event this is.
Which event this is.
Progress callbacks the renderer fires across a single break. Ad-level callbacks carry the asset id (String), matching the portable brain's id-based break/asset model and the conformance sdkSequence shape.
identity-carrying overloads for the ads of a GAM pod (PLAYG-362): IMA reports an adId/creativeId per creative that the manifest cannot know. asset is the synthetic per-ad asset when the manifest does not list it. Default to the plain callbacks so existing implementations (and fakes) that never see a pod need not override.
Playback of asset assetId of brk is at currentTime of duration seconds.
The break-cut timer expired with an ad still in flight; fired before that ad's adend.
The whole break brk ended and content may resume.
A content-covering break ended before its deferred content pause ever landed — an ad that failed faster than the reveal fade (J1/J6). Content never stopped, so no player state transition will announce "break over, content rolling"; the SDK emits the content playing the resumed path would have produced. Defaults to a no-op so fakes need not override.
The renderer soft-ended the current break into its chained successor next, which starts now.
The renderer is about to seek content back to targetSeconds as its own post-break resume-seek, for a break ending at breakEndSeconds.
Asset assetId of brk started playing as ad index (0-based) of total.
identity-carrying overloads for the ads of a GAM pod (PLAYG-362): IMA reports an adId/creativeId per creative that the manifest cannot know. asset is the synthetic per-ad asset when the manifest does not list it. Default to the plain callbacks so existing implementations (and fakes) that never see a pod need not override.
Playback of asset assetId of brk is at currentTime of duration seconds.
The break-cut timer expired with an ad still in flight; fired before that ad's adend.
The whole break brk ended and content may resume.
A content-covering break ended before its deferred content pause ever landed — an ad that failed faster than the reveal fade (J1/J6). Content never stopped, so no player state transition will announce "break over, content rolling"; the SDK emits the content playing the resumed path would have produced. Defaults to a no-op so fakes need not override.
The renderer soft-ended the current break into its chained successor next, which starts now.
The renderer is about to seek content back to targetSeconds as its own post-break resume-seek, for a break ending at breakEndSeconds.
The orchestrator forwards this to BreakScheduler.notifyResumeSeek so the DVR seek-back re-arm does not read this backward step as a genuine user rewind and re-fire the just-completed break (PLAYG-241). Mirrors the web onContentResumeSeek callback. Default no-op for renderers that never resume-seek.
Resolves the break chained immediately after the break with the given id, or null when none/disabled.
The configured ad-insertion mode (OptiViewAdsConfig.adInsertion).
Whether consecutive-break chaining is on.
The largest gap in seconds between two breaks that still chains them.
Whether eligible explicit DAR breaks keep content playing behind the ad.
The redacted GAM configuration; null when GAM is not configured.
Redacted SDK configuration summary; secrets and PII-bearing fields are stripped.
The configured ad-insertion mode (OptiViewAdsConfig.adInsertion).
Whether consecutive-break chaining is on.
The largest gap in seconds between two breaks that still chains them.
Whether eligible explicit DAR breaks keep content playing behind the ad.
The redacted GAM configuration; null when GAM is not configured.
Origin (scheme + host + port) of the URL the session polls — never the path or query, which may carry channel identity or a signed token. Null until the first startSession.
Whether tune-in (join-in-progress) is on.
The shortest remaining break length in seconds that tune-in still plays.
Origin (scheme + host + port) of the URL the session polls — never the path or query, which may carry channel identity or a signed token. Null until the first startSession.
Whether tune-in (join-in-progress) is on.
The shortest remaining break length in seconds that tune-in still plays.
Default SchedulerTicker: drives BreakScheduler.tick() from a coroutine delay loop on the supplied scope, every intervalMs ms. Pure Kotlin/JVM (no Android dependency); on Android the scope is typically the SDK's main-dispatcher scope so ticks land on the main thread.
The portable core scheduler has no internal timer (so it steps deterministically under the conformance harness); this supplies the cadence the web reference gets from its internal setInterval.
Stop ticking. Safe to call when not started.
Default ad-break-cut safety margin, in seconds. A break is always hard-cut back to content at effectiveDuration + this margin at the latest, no matter how long the inserted ad media runs — the SDK never depends on the ad stream reaching its own end before returning to content. The small margin is grace so an ad whose length is close to the break duration can finish cleanly instead of having its final second(s) chopped at the exact boundary. Mirrors the web DEFAULT_AD_BREAK_CUT_SAFETY_MARGIN_SEC.
Default in-memory diagnostics ring-buffer size.
Default scheduler tick cadence (ms) — mirrors the web scheduler's 250 ms setInterval.
Default break-transition duration, in milliseconds. The same 300ms the web core uses (AdPlayerController.TRANSITION_MS) and iOS (layoutTransitionSec), so a break looks the same on every platform unless an integrator says otherwise.
The number of records retained; a non-positive size falls back to DEFAULT_DIAGNOSTICS_BUFFER_SIZE.
Drop all retained records.
Return a copy of the retained records, oldest first.
A bounded, in-memory ring buffer of DiagnosticEvents. Retains the most recent capacity records so OptiViewAds.exportDiagnostics can produce a self-contained report without unbounded growth on long-running live sessions.
The number of records retained; a non-positive size falls back to DEFAULT_DIAGNOSTICS_BUFFER_SIZE.
Append a record, evicting the oldest when the buffer is full.
Functional area of the record.
A single structured diagnostic record.
Severity of the record.
Handler for the structured diagnostic stream.
The redacted configuration of the session.
Recent diagnostics and SDK-event timeline, oldest first.
When the report was generated, in milliseconds since the Unix epoch.
A self-contained, redacted diagnostic report suitable for support/AI tooling.
The redacted configuration of the session.
Recent diagnostics and SDK-event timeline, oldest first.
When the report was generated, in milliseconds since the Unix epoch.
The SDK version that produced the report.
Dependency-free JSON serialization for DiagnosticReport.
The SDK version that produced the report.
How many diagnostic records the in-memory buffer keeps for OptiViewAds.exportDiagnostics.
Structured diagnostics configuration.
How many diagnostic records the in-memory buffer keeps for OptiViewAds.exportDiagnostics.
A fetched manifest response: the exact body bytes (after transfer/content decoding) plus the detached-JWS signature header, both needed to verify the manifest before it is parsed.
Value of the X-Manifest-Signature response header, or null when absent.
Set false to keep GAM off even when the break manifest asks for it.
An OPT-OUT, not an opt-in: GAM activates from the manifest, so the common case needs no configuration at all. This exists for hosts that must not initialise IMA — behind a consent prompt, or in a build that should not reach Google.
Configuration for Google Ad Manager pod serving.
Presence is the OPT-IN: constructing a GamConfig (even an empty one) is what tells the SDK this integration wires IMA. It carries only client-side tuning — the stream identity (networkCode + customAssetKey) comes from the break manifest's vendorConfiguration, so that a client and its backend can no longer disagree about which GAM asset the pods belong to.
The IMA stream activity monitor id, for debugging pod-serving sessions with Google.
GAM/IMA quartile callbacks forwarded to the public SDK event stream. The adIndex/totalAds arguments attribute the quartile to a specific ad of a GAM pod (PLAYG-362); null outside per-ad pod reporting.
Whether any asset parameters were supplied for this session — values are intentionally omitted, only their presence is reported. Set when the session starts: since ADS-221 the only application-supplied layer is SessionConfig.assetParameters, there is no org-level one.
Redacted GAM summary for a DiagnosticReport (ad-tag-parameter VALUES omitted).
Whether any asset parameters were supplied for this session — values are intentionally omitted, only their presence is reported. Set when the session starts: since ADS-221 the only application-supplied layer is SessionConfig.assetParameters, there is no org-level one.
The GAM stream activity monitor id from the configuration, when set.
The GAM stream activity monitor id from the configuration, when set.
The cadence polling is currently running at, or null when it is not running or the implementation does not track it.
Exposed because it BOUNDS every latency measured against a poll: a break may have been in the manifest for up to one interval before the poll that first reported it. Defaulted so an implementation that cannot answer is not forced to lie.
Release resources (stop polling, drop state).
Fetch + parse the manifest once; suspends until it resolves. Throws on fetch/parse failure.
Default ManifestSource: fetches the manifest over HTTP (via an injectable ManifestFetcher), decodes JSON, and validates it through the portable, conformance-locked core ManifestService. Polling is a coroutine loop on the supplied scope. Pure Kotlin/JVM — no Android dependency.
The cadence comes exclusively from the manifest's polling object (active interval while a break is active, idle otherwise — resolvePollingDecision). When the manifest carries no polling object, no loop is started: the manifest is fetched exactly once per session. setActive cancels and restarts a running loop with the interval the new state dictates.
Fetch + parse the manifest once; suspends until it resolves. Throws on fetch/parse failure.
Provide the customer manifest-response interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestResponse here at construction; sources apply it after parsing, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Provide the customer manifest-request interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestRequest here at construction; sources apply it before the network fetch, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Set the manifest URL for the current session (call before fetchManifest/startPolling).
Evidence for the most recent failed read, consumed by the caller raising DA-MANIFEST-FETCH-FAILED. Defaults to null so a custom source keeps working without implementing it — it loses the evidence, not the diagnostic.
Reset session state (stop polling, drop URL + cached manifest) before a new session.
Provide the customer manifest-response interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestResponse here at construction; sources apply it after parsing, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Provide the customer manifest-request interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestRequest here at construction; sources apply it before the network fetch, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Set the manifest URL for the current session (call before fetchManifest/startPolling).
Evidence for the most recent failed read, consumed by the caller raising DA-MANIFEST-FETCH-FAILED. Defaults to null so a custom source keeps working without implementing it — it loses the evidence, not the diagnostic.
What a failed manifest read can say for itself. Twin of ManifestFetchEvidence in packages/core/src/services/ManifestService.ts — see there for why the field set is this small and no smaller.
The short version: "timeout" alone is equally true of a dead backend, a slow edge, and a device on a long network path, and those need opposite responses. hostOk/hostFail are what separate them without a second run.
Fetches the raw manifest response for a URL. Injected so HttpManifestSource can be unit-tested without real networking; the default is OkHttpManifestFetcher.
Context passed to a ManifestResponseInterceptor alongside the manifest.
Diagnostic sink a ManifestSource uses to surface a failed interceptor.
A mocked manifest response. When a ManifestRequestInterceptor returns this, the SDK skips the network and uses body (raw JSON) as the fetched manifest body — parsed + validated exactly as a real network response would be.
Context passed to a ManifestRequestInterceptor alongside the request.
Customer hook to inspect/modify the manifest HTTP request before the SDK fetches it — invoked on the initial fetch and every poll, before the network call. Return a ManifestRequest to redirect/add headers, a ManifestMockResponse to short-circuit the network with a raw body (parsed + validated normally), or null to fetch unchanged. May suspend. If it throws, the SDK emits DA-MANIFEST-REQUEST-INTERCEPT-FAILED and falls back to the normal network fetch. Mirrors the web ManifestRequestInterceptor.
What a ManifestRequestInterceptor may return: a redirect/header override or a mock response.
The outgoing manifest request the SDK is about to make. A ManifestRequestInterceptor may return a (modified) copy to redirect the fetch (url) and/or attach headers.
Customer hook to inspect/modify the break manifest after the SDK has fetched and validated it, before it is scheduled/used. Invoked on the initial fetch and on every poll, with the already-parsed, typed BreakManifest — never raw JSON. Returns the manifest to use (modified or unchanged); the returned value is used directly without re-validation. May suspend. If it throws, the SDK emits DA-MANIFEST-INTERCEPT-FAILED and falls back to the un-modified parsed manifest (the fetch does not fail). Mirrors the web ManifestResponseInterceptor.
The cadence polling is currently running at, or null when it is not running or the implementation does not track it.
Exposed because it BOUNDS every latency measured against a poll: a break may have been in the manifest for up to one interval before the poll that first reported it. Defaulted so an implementation that cannot answer is not forced to lie.
Release resources (stop polling, drop state).
Fetch + parse the manifest once; suspends until it resolves. Throws on fetch/parse failure.
The manifest fetch + poll boundary. The portable :ads-sdk-core ManifestService only parses + validates a decoded manifest (so its validation stays conformance-locked across platforms); the actual network fetch and the polling timer are platform concerns and live behind this interface. HttpManifestSource is the default implementation (OkHttp + coroutine poll loop); tests and the conformance driver supply a fake.
This mirrors the additional responsibilities the web ManifestService carries on top of parsing (setManifestUrl / fetchManifest / startPolling / setActive / reset), keeping the orchestrator's call sites identical to the TS reference.
Fetch + parse the manifest once; suspends until it resolves. Throws on fetch/parse failure.
Provide the customer manifest-response interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestResponse here at construction; sources apply it after parsing, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Provide the customer manifest-request interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestRequest here at construction; sources apply it before the network fetch, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Set the manifest URL for the current session (call before fetchManifest/startPolling).
Evidence for the most recent failed read, consumed by the caller raising DA-MANIFEST-FETCH-FAILED. Defaults to null so a custom source keeps working without implementing it — it loses the evidence, not the diagnostic.
Reset session state (stop polling, drop URL + cached manifest) before a new session.
Provide the customer manifest-response interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestResponse here at construction; sources apply it after parsing, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Provide the customer manifest-request interceptor (and a diagnostic sink for when it throws). The SDK forwards OptiViewAdsConfig.interceptManifestRequest here at construction; sources apply it before the network fetch, on the initial fetch and every poll. Default no-op so custom sources need not support it.
Set the manifest URL for the current session (call before fetchManifest/startPolling).
Evidence for the most recent failed read, consumed by the caller raising DA-MANIFEST-FETCH-FAILED. Defaults to null so a custom source keeps working without implementing it — it loses the evidence, not the diagnostic.
Whole-call budget for one manifest fetch.
OkHttp's DEFAULTS are 10s connect and 10s read, which sounds covered but is not: both are per-operation. A server that accepts the connection and then dribbles bytes — one byte inside every read window — satisfies each timeout forever and the call never returns. callTimeout is the only one that bounds the whole thing, and it defaults to 0, meaning no limit. The initial fetch is awaited by startSession, so an unbounded call there is a startSession that never resolves and reports nothing.
15s leaves room for a slow-but-real mobile fetch (connect + TLS + body) while staying inside the harness's 30s per-command budget, so the device fails with a specific manifest error rather than a generic timeout.
Defaults of the OkHttp client the fetcher builds when none is supplied.
OkHttp-backed ManifestFetcher. The blocking call runs on Dispatchers.IO.
Safety margin, in seconds, added to a break's effective duration to form the hard cut-off at which the SDK always returns to content — regardless of whether the inserted ad media has reached its own end. Set to 0.0 to cut exactly at the break boundary. Mirrors the web adBreakCutSafetyMarginSec.
Ad insertion strategy; defaults to AdInsertionMode.AUTO, which resolves to overlay on Android.
Ad preload strategy; defaults to AdPreloadMode.AUTO, matching the web DEFAULT_AD_PRELOAD_MODE. Android has no browser UA, so auto resolves to AdPreloadMode.PARALLEL unless the adapter reports supportsParallelBuffering == false — with the AUTO default that capability hint is authoritative without any configuration.
Pre-break warning thresholds (seconds before a non-pre-roll break) at which the SDK emits an adbreakstatus with phase = upcoming. Defaults to none. Mirrors the web breakWarnings config. See BreakWarningsConfig.
Consecutive-break chaining; defaults to on with a 2-second gap.
Keep the content player PLAYING through an eligible replacement break instead of pausing it and seeking back afterwards.
The resume seek is bounded by the HLS holdback — EXT-X-SERVER-CONTROL:HOLD-BACK or three target durations — which on a feed declaring TARGETDURATION:10 for 6s segments puts the resume point inside published media the player still refuses to seek to. Content that never pauses advances 1:1 with the break and arrives there by simply continuing, so there is no seek to be clipped. Hidden and muted for the duration, and pinned to the lowest rendition so it does not cost a second full-quality stream.
Additive: every other flow keeps the pause/resume behaviour unchanged. Defaults to false.
Pin this session's delivery architecture instead of letting the break manifest's delivery rules steer it (ADS-326).
Unset (the default) is manifest-steered: the manifest decides, falling back to com.dolby.optiview.ads.core.DeliveryMode.SGAI. Set it only when the host must decide client-side — it wins over the manifest and the override is reported through DA-DELIVERY-MODE-OVERRIDDEN. Mirrors the web mode.
Structured diagnostics settings.
Which side keeps audio during a double-format break: the ad (default) or content.
double is the only format where content and ad are both on screen and both playing, so it is the only one where two soundtracks can run at once. Exactly one is audible; the other is silenced for the break and restored when it ends.
Mirrors the web doubleBoxAudio.
Org-level SDK configuration, fixed for the lifetime of the OptiViewAds instance. Chaining uses the brain's already-resolved ChainingConfig; the default below matches the web DEFAULT_CHAINING (enabled, 2s gap). tuneIn matches the web DEFAULT_TUNE_IN (enabled, 5s minimum remaining duration).
Safety margin, in seconds, added to a break's effective duration to form the hard cut-off at which the SDK always returns to content — regardless of whether the inserted ad media has reached its own end. Set to 0.0 to cut exactly at the break boundary. Mirrors the web adBreakCutSafetyMarginSec.
Ad insertion strategy; defaults to AdInsertionMode.AUTO, which resolves to overlay on Android.
Ad preload strategy; defaults to AdPreloadMode.AUTO, matching the web DEFAULT_AD_PRELOAD_MODE. Android has no browser UA, so auto resolves to AdPreloadMode.PARALLEL unless the adapter reports supportsParallelBuffering == false — with the AUTO default that capability hint is authoritative without any configuration.
Pre-break warning thresholds (seconds before a non-pre-roll break) at which the SDK emits an adbreakstatus with phase = upcoming. Defaults to none. Mirrors the web breakWarnings config. See BreakWarningsConfig.
Consecutive-break chaining; defaults to on with a 2-second gap.
Keep the content player PLAYING through an eligible replacement break instead of pausing it and seeking back afterwards.
Pin this session's delivery architecture instead of letting the break manifest's delivery rules steer it (ADS-326).
Structured diagnostics settings.
Which side keeps audio during a double-format break: the ad (default) or content.
Optional hook to inspect/modify the manifest HTTP request before the SDK fetches it (initial fetch and every poll). Can redirect the URL, add headers, or short-circuit the network with a mocked raw body (parsed + validated normally). May suspend. On throw emits DA-MANIFEST-REQUEST-INTERCEPT-FAILED and falls back to the normal network fetch. See ManifestRequestInterceptor. The SDK forwards it to the ManifestSource; the default HttpManifestSource applies it.
Optional hook to inspect/modify the break manifest after the SDK fetches and validates it, before it is scheduled. Receives the typed, parsed BreakManifest (initial fetch and every poll) and returns the manifest to use. May suspend. See ManifestResponseInterceptor. The SDK forwards it to the ManifestSource; the default HttpManifestSource applies it.
How long, in seconds, to wait for the stream's EXT-X-PROGRAM-DATE-TIME on a wallclock-timebase session before concluding the stream carries none.
The adapter around the application's content player.
Selects how timebase: "pts" break starts are resolved. PtsSource.MEDIA_TIME uses the manifest start directly. PtsSource.ANVATO_CUE tracks Anvato timed-metadata cues from the content player — HLS ID3 GEOB frames with description Anvatos (MIME application/json) and DASH emsg events with scheme urn:anvato:es1:052016 — whose payload is a query string of the form type=cue&pts=<seconds>. A PTS break is then scheduled at the media time of the observed cue whose pts matches the break's start (±5 ms); a break whose cue has not been observed yet stays pending (surfaced once per break via the DA-ANVATO-CUE-PENDING diagnostic). SGAI only; has no effect on wallclock-timebase manifests. Mirrors the web ptsSource. Defaults to PtsSource.MEDIA_TIME.
How the picture changes at the edges of a break; see TransitionConfig.
Tune-in (join-in-progress); defaults to on with a 5-second minimum remaining duration.
Optional hook to inspect/modify the manifest HTTP request before the SDK fetches it (initial fetch and every poll). Can redirect the URL, add headers, or short-circuit the network with a mocked raw body (parsed + validated normally). May suspend. On throw emits DA-MANIFEST-REQUEST-INTERCEPT-FAILED and falls back to the normal network fetch. See ManifestRequestInterceptor. The SDK forwards it to the ManifestSource; the default HttpManifestSource applies it.
Optional hook to inspect/modify the break manifest after the SDK fetches and validates it, before it is scheduled. Receives the typed, parsed BreakManifest (initial fetch and every poll) and returns the manifest to use. May suspend. See ManifestResponseInterceptor. The SDK forwards it to the ManifestSource; the default HttpManifestSource applies it.
How long, in seconds, to wait for the stream's EXT-X-PROGRAM-DATE-TIME on a wallclock-timebase session before concluding the stream carries none.
A session is normally started before the content player has loaded its source, so the scheduler's first ticks see no PDT even on a stream that does carry it. Those ticks make no scheduling decision, rather than matching breaks against the system clock — which runs ahead of the live playhead by the stream's latency and would fire a break early (PLAYG-360).
This is a backstop, not a fixed delay. The SDK stops waiting at whichever comes first: content has been playing for ~1s and still exposes no PDT (direct evidence about the stream — DA-PDT-MISSING is emitted once and the clock takes over immediately, so a join-in-progress break is not delayed below the tune-in minimum), or this window elapses (the backstop for a player that never starts).
Set 0.0 to fall back to the system clock immediately. Has no effect on pts-timebase manifests. Mirrors the web pdtGraceSeconds.
The adapter around the application's content player.
Selects how timebase: "pts" break starts are resolved. PtsSource.MEDIA_TIME uses the manifest start directly. PtsSource.ANVATO_CUE tracks Anvato timed-metadata cues from the content player — HLS ID3 GEOB frames with description Anvatos (MIME application/json) and DASH emsg events with scheme urn:anvato:es1:052016 — whose payload is a query string of the form type=cue&pts=<seconds>. A PTS break is then scheduled at the media time of the observed cue whose pts matches the break's start (±5 ms); a break whose cue has not been observed yet stays pending (surfaced once per break via the DA-ANVATO-CUE-PENDING diagnostic). SGAI only; has no effect on wallclock-timebase manifests. Mirrors the web ptsSource. Defaults to PtsSource.MEDIA_TIME.
How the picture changes at the edges of a break; see TransitionConfig.
Tune-in (join-in-progress); defaults to on with a 5-second minimum remaining duration.
Listener for a single OptiViewAdsEventType (registered via OptiViewAds.addEventListener).
An individual ad starts playing; see AdBeginEvent.
An ad break starts; see AdBreakBeginEvent.
An ad break ends; see AdBreakEndEvent.
The break state or countdown changed; see AdBreakStatusEvent.
A polled manifest switched the session to another ads channel; see AdChannelChangeEvent.
The viewer activated an ad click-through; see AdClickEvent.
An individual ad finishes; see AdEndEvent.
Playback failed; see AdErrorEvent.
An ad reached 25% completion; see AdFirstQuartileEvent.
An ad reached 50% completion; see AdMidpointEvent.
An ad reached 75% completion; see AdThirdQuartileEvent.
Ad playback progressed; see AdTimeupdateEvent.
Playback started or resumed; see PlayingEvent.
The unified mute or volume state changed; see VolumeChangeEvent.
Playback stalled for buffering; see WaitingEvent.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
The SDK event type tags (mirrors the TS OptiViewAdsEventType).
An ad break starts; see AdBreakBeginEvent.
An ad break ends; see AdBreakEndEvent.
An individual ad starts playing; see AdBeginEvent.
An individual ad finishes; see AdEndEvent.
Playback failed; see AdErrorEvent.
An ad reached 25% completion; see AdFirstQuartileEvent.
An ad reached 50% completion; see AdMidpointEvent.
An ad reached 75% completion; see AdThirdQuartileEvent.
Ad playback progressed; see AdTimeupdateEvent.
The viewer activated an ad click-through; see AdClickEvent.
The break state or countdown changed; see AdBreakStatusEvent.
Playback stalled for buffering; see WaitingEvent.
Playback started or resumed; see PlayingEvent.
The unified mute or volume state changed; see VolumeChangeEvent.
A polled manifest switched the session to another ads channel; see AdChannelChangeEvent.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Which event this is.
Static information about the SDK.
Fixed configuration for the lifetime of the instance.
Plays the ads; the Android runtime's OverlayAdRenderer.
Fetches and polls the Break Manifest; normally HttpManifestSource.
Drives break scheduling; normally CoroutineSchedulerTicker.
The coroutine scope the SDK works in; the default is fine for apps.
The time source; the default is the system clock (tests inject a fake).
Subscribe to an SDK event.
Report a click on the ad currently on screen and emit the public adclick event carrying the asset's declared interaction.clickThrough URL (if any). Called by the renderer on a viewer tap, or programmatically by the application (e.g. a custom "visit advertiser" button). The SDK deliberately does NOT open the URL — that is the application's decision. Returns the clickThrough URL when a click was registered, null otherwise. Mirrors the web/iOS clickAd().
Clean up all resources. Call when the SDK is no longer needed.
Stop monetization for the current content.
Produce a self-contained, redacted diagnostic report for support / AI tooling.
The current ad-break status snapshot, the same one AdBreakStatusEvent carries.
What the SDK currently has on the player surface — see PresentationState.
Answered here because both halves are the SDK's own decisions: it knows whether a break is rendering, and it is what re-lays-out a break when picture-in-picture is entered mid-ad. An application deriving this itself would be duplicating rules that change.
The OptiView Ads SDK entry point: one instance per content player, living as long as the player. It polls the Break Manifest of the current session, schedules the breaks against the player's timeline through the configured PlayerAdapter, plays them through the AdRenderer, and reports what happens on the event stream (addEventListener) and the diagnostics stream (onDiagnostic, exportDiagnostics).
Typical use: construct it once with an OptiViewAdsConfig and the Android runtime's OverlayAdRenderer, startSession for each piece of content, endSession when the content stops, and destroy when the player goes away.
Fixed configuration for the lifetime of the instance.
Plays the ads; the Android runtime's OverlayAdRenderer.
Fetches and polls the Break Manifest; normally HttpManifestSource.
Drives break scheduling; normally CoroutineSchedulerTicker.
The coroutine scope the SDK works in; the default is fine for apps.
The time source; the default is the system clock (tests inject a fake).
Subscribe to an SDK event.
Report a click on the ad currently on screen and emit the public adclick event carrying the asset's declared interaction.clickThrough URL (if any). Called by the renderer on a viewer tap, or programmatically by the application (e.g. a custom "visit advertiser" button). The SDK deliberately does NOT open the URL — that is the application's decision. Returns the clickThrough URL when a click was registered, null otherwise. Mirrors the web/iOS clickAd().
Stop monetization for the current content.
Produce a self-contained, redacted diagnostic report for support / AI tooling.
The current ad-break status snapshot, the same one AdBreakStatusEvent carries.
What the SDK currently has on the player surface — see PresentationState.
Whether an ad is currently playing.
Whether the content player is in picture-in-picture — as observed by the renderer's own Activity watcher, or as last reported through setPictureInPicture where that watcher could not attach.
Whether a session is currently active.
Unsubscribe from the structured diagnostic stream.
Subscribe to the structured diagnostic stream.
Unsubscribe from an SDK event.
Tell the SDK whether the content player is in picture-in-picture.
Skip the in-progress ad break, honoring the manifest's skip policy: the break must declare controls.skipOffset and at least that many seconds of the break must have elapsed. Returns true when the skip was applied (the break cuts to content, emitting the balanced adend + adbreakend), false when suppressed (no active break, no skip control, or before the offset). Use getAdBreakStatus to drive a "Skip in Ns" affordance. Mirrors the web/iOS skipAd().
Start monetization for a piece of content. Begins manifest polling and (if configured) GAM session init. Ends any previously active session first.
Merge macros into the asset-parameter macros of the active session. Each name replaces the previous value for that name; other names stay. A null value removes the customer macro so the built-in $OPTIVIEW_* value (if any) applies again. When a GAM stream is active the effective ad tag parameters are resolved again and pushed to IMA; VAST tag URLs use the new values on the next ad request. No-op (with a warning) without an active session.
Merge explicit-value asset-parameter macros into the active session. A callback returning com.dolby.optiview.ads.core.AssetParameterMacroValue.Empty omits the containing parameter (or cust_params pair); a null entry removes the customer macro.
Replace the live-update layer of the asset parameters on the active session. Applies to future ad breaks — no re-initialization needed.
Whether an ad is currently playing.
Whether the content player is in picture-in-picture — as observed by the renderer's own Activity watcher, or as last reported through setPictureInPicture where that watcher could not attach.
Whether a session is currently active.
Unsubscribe from the structured diagnostic stream.
Subscribe to the structured diagnostic stream.
Pause content playback. No-op while a content-locking ad break is active.
Start or resume content playback. No-op while a content-locking ad break is active.
Unsubscribe from an SDK event.
Tell the SDK whether the content player is in picture-in-picture.
You normally do not need to call this. The Android runtime's OverlayAdRenderer resolves the Activity from the Context it was built with, or from the overlay's own view tree, and watches it — so a transition is picked up on its own, including one the VIEWER started with the system button or the swipe-home gesture, which no app-level callback would tell you about either. Web and iOS have always detected picture-in-picture themselves; this closes the gap on Android.
Call it only when the SDK reports DA-PIP-AUTODETECT-UNAVAILABLE, which means no Activity could be reached either way (an application Context under an overlay that hangs under no Activity, or a host that is not an Activity). Then forward Activity.onPictureInPictureModeChanged(isInPictureInPictureMode, ...) here, and once at startup if the app can be launched straight into picture-in-picture.
While active, every break plays as BreakFormat.SINGLE: one fullscreen ad, no companion, content paused, and on live the usual single-break latency restore on resume. The declared format still reaches diagnostics via DA-PIP-FORMAT-OVERRIDE; the public events report what actually plays.
Idempotent — repeated calls with the same value are ignored. So a host that forwards the lifecycle callback anyway costs nothing: whichever path sees the change first wins and the other is a no-op.
Skip the in-progress ad break, honoring the manifest's skip policy: the break must declare controls.skipOffset and at least that many seconds of the break must have elapsed. Returns true when the skip was applied (the break cuts to content, emitting the balanced adend + adbreakend), false when suppressed (no active break, no skip control, or before the offset). Use getAdBreakStatus to drive a "Skip in Ns" affordance. Mirrors the web/iOS skipAd().
Start monetization for a piece of content. Begins manifest polling and (if configured) GAM session init. Ends any previously active session first.
Merge explicit-value asset-parameter macros into the active session. A callback returning com.dolby.optiview.ads.core.AssetParameterMacroValue.Empty omits the containing parameter (or cust_params pair); a null entry removes the customer macro.
Merge macros into the asset-parameter macros of the active session. Each name replaces the previous value for that name; other names stay. A null value removes the customer macro so the built-in $OPTIVIEW_* value (if any) applies again. When a GAM stream is active the effective ad tag parameters are resolved again and pushed to IMA; VAST tag URLs use the new values on the next ad request. No-op (with a warning) without an active session.
Replace the live-update layer of the asset parameters on the active session. Applies to future ad breaks — no re-initialization needed.
Highest precedence of the three layers: it overrides both SessionConfig.assetParameters and the manifest's per-asset assetParameters, per key. It replaces the previous update rather than accumulating onto it, matching IMA's replaceAdTagParameters() underneath.
Consumed by GAM pod requests and appended to VAST tag URLs. No-op (with a warning) without an active session.
The SDK's ad player.
The application's content player.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Which player a playback event originated from.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Playback started or resumed after stalling or pausing, on the content player or the ad player.
Which player started playing.
Which event this is.
What the SDK is presenting right now, returned by OptiViewAds.getPresentationState.
Deliberately answered by the SDK rather than derived by the application: the SDK is what decides whether an ad occupies the surface and what picture-in-picture does to a break, so an app that inferred it would be re-implementing that decision and would drift the moment the rules change (they did — PiP now re-lays-out a break in flight).
Useful to any integrator drawing its own overlay UI; the test agent forwards it verbatim.
Whether the host has reported the content player to be in picture-in-picture.
Which media currently owns the surface.
An ad is on screen (a break is rendering).
No ad is rendering, so the surface belongs to the main content.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Which media the SDK currently has on the player surface.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Match the manifest start against Anvato in-stream cues.
Use the manifest start directly against the player's media time.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Invoked by a renderer when the viewer taps/clicks the ad surface during a break. The orchestrator resolves the current break/asset + clickThrough and emits the public adclick event.
Sink for structured diagnostics emitted by a renderer. The orchestrator wires this to its own diagnose(...) so renderer-side codes (e.g. DA-VAST-*) flow through the same diagnostic stream/buffer as the SDK's.
Drives the portable BreakScheduler.tick() on a fixed cadence.
The core :ads-sdk-core scheduler intentionally has no internal timer (so it steps deterministically under the conformance harness), whereas the web scheduler runs an internal 250 ms setInterval. On Android the platform supplies that cadence — a coroutine delay loop, a Handler, or a Choreographer — behind this seam, so the orchestrator's timing wiring stays identical to the web reference.
Stop ticking. Safe to call when not started.
How this session's breaks relate to the content timeline, which decides where content resumes after a break: com.dolby.optiview.ads.core.AdInsertionType.REPLACEMENT (DAR) skips the replaced window; com.dolby.optiview.ads.core.AdInsertionType.INSERTION (DAI) resumes at the cue. When null, the manifest's resumeOffset drives the portable resolveResumePoint.
Macro callbacks with explicit AssetParameterMacroValue.Text, AssetParameterMacroValue.Empty, and AssetParameterMacroValue.Unresolved states. Uses the same $-prefixed names as assetParameterMacros. When a name is in both maps, this map wins.
Customer macros for the $ tokens in asset-parameter values. Keys are the $-prefixed names as they appear in the break manifest; each callback is invoked when an ad request is built and its result replaces every occurrence of the name inside a value, so "\$OPTIVIEW_PLAYER_WIDTH\$x\$OPTIVIEW_PLAYER_HEIGHT\$" becomes "1920x1080". A fixed value is a constant callback: mapOf("\$SEGMENT\$" to { "sports" }); returning null leaves the macro unresolved. Use assetParameterMacroValues when an empty value should omit the parameter that contains the macro.
Customer macros are consulted before the built-in $OPTIVIEW_* set (com.dolby.optiview.ads.core.OptiViewAssetParameterMacros), so a built-in may be overridden. An unresolved $OPTIVIEW_* macro or a registered macro without a value is sent literally and reported as DA-ASSET-MACRO-UNKNOWN; any other unresolved $NAME$ token is sent literally without a diagnostic. Cleared when the session ends.
Ad parameters for the assets played in this session — targeting, custom params, anything the ad server keys on.
Vendor-neutral by name; for GAM these become IMA's adTagParameters. Merged on top of each asset's own assetParameters from the break manifest, per key, so overriding one key does not discard the rest of what the break author authored. OptiViewAds.updateAssetParameters overrides both.
Per-session configuration passed to OptiViewAds.startSession. Changes per piece of content / channel switch.
How this session's breaks relate to the content timeline, which decides where content resumes after a break: com.dolby.optiview.ads.core.AdInsertionType.REPLACEMENT (DAR) skips the replaced window; com.dolby.optiview.ads.core.AdInsertionType.INSERTION (DAI) resumes at the cue. When null, the manifest's resumeOffset drives the portable resolveResumePoint.
Customer macros for the $ tokens in asset-parameter values. Keys are the $-prefixed names as they appear in the break manifest; each callback is invoked when an ad request is built and its result replaces every occurrence of the name inside a value, so "\$OPTIVIEW_PLAYER_WIDTH\$x\$OPTIVIEW_PLAYER_HEIGHT\$" becomes "1920x1080". A fixed value is a constant callback: mapOf("\$SEGMENT\$" to { "sports" }); returning null leaves the macro unresolved. Use assetParameterMacroValues when an empty value should omit the parameter that contains the macro.
Macro callbacks with explicit AssetParameterMacroValue.Text, AssetParameterMacroValue.Empty, and AssetParameterMacroValue.Unresolved states. Uses the same $-prefixed names as assetParameterMacros. When a name is in both maps, this map wins.
Ad parameters for the assets played in this session — targeting, custom params, anything the ad server keys on.
Full URL of the break manifest for this content. Fetched and polled exactly as given — the SDK never composes, rewrites or appends to it, so the URL structure is entirely the backend's to decide.
Full URL of the break manifest for this content. Fetched and polled exactly as given — the SDK never composes, rewrites or appends to it, so the URL structure is entirely the backend's to decide.
How long the transition animates, in milliseconds.
What the renderer should actually animate over; 0 means "snap".
How the picture changes at the edges of a break — content to ad and back.
The default is a 300ms cross-fade, matching the web core's TRANSITION_MS and the iOS layoutTransitionSec, so the three cores look the same out of the box. It is configurable because an integrator with their own presentation — a TV app that wants a straight cut, or a host that already animates around the player — needs a way to say so; TransitionType.NONE gives back exactly the previous cut-based behaviour.
durationMs is ignored when type is TransitionType.NONE.
How long the transition animates, in milliseconds.
What the renderer should actually animate over; 0 means "snap".
The kind of transition.
The kind of transition.
Content and ad cross-fade into each other (the default).
No animation: every transition cuts, which is what the renderer did before.
Returns a representation of an immutable list of all enum entries, in the order they're declared.
This method may be used to iterate over the enum entries.
How a break transition is played.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
Returns an array containing the constants of this enum type, in the order they're declared.
Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)
if this enum type has no constant with the specified name
Returns an array containing the constants of this enum type, in the order they're declared.
This method may be used to iterate over the constants.
Seconds of the break that had already passed when the viewer joined.
Tune-in (join-in-progress) detail attached to an AdBreakBeginEvent when the viewer joined while the break was already in progress. remainingSec is the effective duration the break is presented for.
Prefer AdBreakBeginEvent.elapsedSec / AdBreakBeginEvent.remainingSec, which are reported for every break-start. Reading the values through this object misses every part-way join that fell inside the scheduler's start tolerance.
Seconds of the break the viewer is presented with.
Unified audio state changed — the Kotlin mirror of the TS VolumeChangeEvent.
"Unified" is the point: muted/volume describe what the VIEWER hears, not one player's field. On Android the ad ExoPlayer renders both static creatives and IMA VAST ads, so a single target covers everything audible during a break.
Without this event an application had no way to keep a mute button in sync short of polling. Worse, the Kotlin SDK had no unified audio surface at all: muting reached only the CONTENT player, so a muted viewer still heard every ad break at full volume. Caught by catalog-controls G4.
Which event this is.
Playback stalled for buffering, on the content player or the ad player.
Which player stalled.
Which event this is.
OptiViewAds and its configuration (OptiViewAdsConfig, SessionConfig, GamConfig), the event types, the diagnostics types, and the platform seams with their default JVM implementations (HttpManifestSource, CoroutineSchedulerTicker).
An individual ad starts playing. A GAM pod reports one adbegin per ad it was filled with.
An ad break starts and content is paused (or, for lshape_content and overlay breaks, keeps playing).
An ad break ends and content resumes.
Lifecycle phase reported by AdBreakStatus. Mirrors the TS AdBreakPhase.
Playback-gated snapshot of an ad break for UI countdowns — the Kotlin mirror of the web AdBreakStatus (packages/core/src/types/Events.ts). The SDK owns the timebase and the player-gated ticking flag; the application renders the badge/overlay. Emitted on the AdBreakStatusEvent and returned by OptiViewAds.getAdBreakStatus.
Event emitted when the status of the current or upcoming ad break changes. Carries a complete AdBreakStatus snapshot. Mirrors the TS AdBreakStatusEvent.
A polled manifest described a different ads channel and the SDK re-aligned its ad setup to it while the session and content playback continued. Fires once per switch, after a break in progress has finished and the new manifest is applied.
The viewer clicked/tapped the ad on screen (or the application called OptiViewAds.clickAd programmatically) — the Kotlin mirror of the iOS/web adclick event. Carries the asset's declared interaction.clickThrough URL when the manifest supplies one; the SDK deliberately does NOT open it — that is the application's decision.
The creative identity IMA reports for an ad of a GAM pod (PLAYG-361/362). Absent for every other asset kind, where the manifest asset already identifies the ad.
An individual ad finishes.
Playback failed. Emitted for both the content player and the SDK's ad player; source tells them apart. An ad error is not fatal: the SDK skips the asset and continues the break or resumes content.
An ad reached 25% completion.
Ad insertion strategy. auto resolves per device (iPhone/iPod → adaptive or shared-element; otherwise overlay). On Android this resolves to OVERLAY.
An ad reached 50% completion.
Ad preload strategy. auto resolves at runtime (decoder-limited devices → SINGLE_DECODER, otherwise PARALLEL).
The ad-rendering boundary — the Kotlin counterpart of the web AdPlayerController. The orchestrator (OptiViewAds) stays player-agnostic and delegates everything that touches a media surface, an overlay, or GAM/IMA to an AdRenderer. The Android runtime renderer (Media3 ad player + overlay + IMA DAI) implements this in P4b; tests and the conformance driver supply a fake.
An ad reached 75% completion.
Ad playback progressed; fires on each time update of the ad player (about 4 Hz). For a GAM pod the times describe the whole pod, not the ad on screen.
Progress callbacks the renderer fires across a single break. Ad-level callbacks carry the asset id (String), matching the portable brain's id-based break/asset model and the conformance sdkSequence shape.
Resolves the break chained immediately after the break with the given id, or null when none/disabled.
Redacted SDK configuration summary; secrets and PII-bearing fields are stripped.
Default SchedulerTicker: drives BreakScheduler.tick() from a coroutine delay loop on the supplied scope, every intervalMs ms. Pure Kotlin/JVM (no Android dependency); on Android the scope is typically the SDK's main-dispatcher scope so ticks land on the main thread.
A bounded, in-memory ring buffer of DiagnosticEvents. Retains the most recent capacity records so OptiViewAds.exportDiagnostics can produce a self-contained report without unbounded growth on long-running live sessions.
A single structured diagnostic record.
Handler for the structured diagnostic stream.
A self-contained, redacted diagnostic report suitable for support/AI tooling.
Structured diagnostics configuration.
A fetched manifest response: the exact body bytes (after transfer/content decoding) plus the detached-JWS signature header, both needed to verify the manifest before it is parsed.
GAM/IMA quartile callbacks forwarded to the public SDK event stream. The adIndex/totalAds arguments attribute the quartile to a specific ad of a GAM pod (PLAYG-362); null outside per-ad pod reporting.
Redacted GAM summary for a DiagnosticReport (ad-tag-parameter VALUES omitted).
Default ManifestSource: fetches the manifest over HTTP (via an injectable ManifestFetcher), decodes JSON, and validates it through the portable, conformance-locked core ManifestService. Polling is a coroutine loop on the supplied scope. Pure Kotlin/JVM — no Android dependency.
Fetches the raw manifest response for a URL. Injected so HttpManifestSource can be unit-tested without real networking; the default is OkHttpManifestFetcher.
What a failed manifest read can say for itself. Twin of ManifestFetchEvidence in packages/core/src/services/ManifestService.ts — see there for why the field set is this small and no smaller.
Context passed to a ManifestResponseInterceptor alongside the manifest.
Diagnostic sink a ManifestSource uses to surface a failed interceptor.
A mocked manifest response. When a ManifestRequestInterceptor returns this, the SDK skips the network and uses body (raw JSON) as the fetched manifest body — parsed + validated exactly as a real network response would be.
The outgoing manifest request the SDK is about to make. A ManifestRequestInterceptor may return a (modified) copy to redirect the fetch (url) and/or attach headers.
Context passed to a ManifestRequestInterceptor alongside the request.
Customer hook to inspect/modify the manifest HTTP request before the SDK fetches it — invoked on the initial fetch and every poll, before the network call. Return a ManifestRequest to redirect/add headers, a ManifestMockResponse to short-circuit the network with a raw body (parsed + validated normally), or null to fetch unchanged. May suspend. If it throws, the SDK emits DA-MANIFEST-REQUEST-INTERCEPT-FAILED and falls back to the normal network fetch. Mirrors the web ManifestRequestInterceptor.
What a ManifestRequestInterceptor may return: a redirect/header override or a mock response.
Customer hook to inspect/modify the break manifest after the SDK has fetched and validated it, before it is scheduled/used. Invoked on the initial fetch and on every poll, with the already-parsed, typed BreakManifest — never raw JSON. Returns the manifest to use (modified or unchanged); the returned value is used directly without re-validation. May suspend. If it throws, the SDK emits DA-MANIFEST-INTERCEPT-FAILED and falls back to the un-modified parsed manifest (the fetch does not fail). Mirrors the web ManifestResponseInterceptor.
The manifest fetch + poll boundary. The portable :ads-sdk-core ManifestService only parses + validates a decoded manifest (so its validation stays conformance-locked across platforms); the actual network fetch and the polling timer are platform concerns and live behind this interface. HttpManifestSource is the default implementation (OkHttp + coroutine poll loop); tests and the conformance driver supply a fake.
OkHttp-backed ManifestFetcher. The blocking call runs on Dispatchers.IO.
The OptiView Ads SDK entry point: one instance per content player, living as long as the player. It polls the Break Manifest of the current session, schedules the breaks against the player's timeline through the configured PlayerAdapter, plays them through the AdRenderer, and reports what happens on the event stream (addEventListener) and the diagnostics stream (onDiagnostic, exportDiagnostics).
Org-level SDK configuration, fixed for the lifetime of the OptiViewAds instance. Chaining uses the brain's already-resolved ChainingConfig; the default below matches the web DEFAULT_CHAINING (enabled, 2s gap). tuneIn matches the web DEFAULT_TUNE_IN (enabled, 5s minimum remaining duration).
Base type for all SDK events.
Listener for a single OptiViewAdsEventType (registered via OptiViewAds.addEventListener).
The SDK event type tags (mirrors the TS OptiViewAdsEventType).
Which player a playback event originated from.
Playback started or resumed after stalling or pausing, on the content player or the ad player.
What the SDK is presenting right now, returned by OptiViewAds.getPresentationState.
Which media the SDK currently has on the player surface.
Invoked by a renderer when the viewer taps/clicks the ad surface during a break. The orchestrator resolves the current break/asset + clickThrough and emits the public adclick event.
Sink for structured diagnostics emitted by a renderer. The orchestrator wires this to its own diagnose(...) so renderer-side codes (e.g. DA-VAST-*) flow through the same diagnostic stream/buffer as the SDK's.
Drives the portable BreakScheduler.tick() on a fixed cadence.
Per-session configuration passed to OptiViewAds.startSession. Changes per piece of content / channel switch.
How the picture changes at the edges of a break — content to ad and back.
How a break transition is played.
Tune-in (join-in-progress) detail attached to an AdBreakBeginEvent when the viewer joined while the break was already in progress. remainingSec is the effective duration the break is presented for.
Unified audio state changed — the Kotlin mirror of the TS VolumeChangeEvent.
Playback stalled for buffering, on the content player or the ad player.
Default ad-break-cut safety margin, in seconds. A break is always hard-cut back to content at effectiveDuration + this margin at the latest, no matter how long the inserted ad media runs — the SDK never depends on the ad stream reaching its own end before returning to content. The small margin is grace so an ad whose length is close to the break duration can finish cleanly instead of having its final second(s) chopped at the exact boundary. Mirrors the web DEFAULT_AD_BREAK_CUT_SAFETY_MARGIN_SEC.
Default in-memory diagnostics ring-buffer size.
Default scheduler tick cadence (ms) — mirrors the web scheduler's 250 ms setInterval.
Default break-transition duration, in milliseconds. The same 300ms the web core uses (AdPlayerController.TRANSITION_MS) and iOS (layoutTransitionSec), so a break looks the same on every platform unless an integrator says otherwise.
Dependency-free JSON serialization for DiagnosticReport.
Dependency-free JSON serialization for DiagnosticReport.
Emits the same report schema as the web SDK (OptiViewAds.exportDiagnostics() in @dolby-optiview/ads-sdk-core) so a native report can be fed directly to the @dolby-optiview/ads-sdk-mcp troubleshooting tools and the AI artifacts — i.e. config carries a nested chaining: { enabled, maxGapSeconds }, and level/category are their lowercase string values. This is the format a support engineer or AI assistant consumes; it is verified cross-platform by the MCP test fixtures.
The player-agnostic orchestrator of the OptiView Ads SDK. OptiViewAds wires the core to a PlayerAdapter, runs the session lifecycle (startSession, endSession), emits the public event stream (OptiViewAdsEvent) and the diagnostics stream, and defines the seams the Android runtime implements (AdRenderer, ManifestSource, SchedulerTicker). Pure Kotlin/JVM; the Android-specific pieces live in ads-sdk-runtime.
The API reference for the OptiView Ads SDK on Android and Android TV. The SDK implements Server-Guided Ad Insertion: it polls a Break Manifest, schedules the breaks against the content player's timeline, plays the ads, and reports the impressions. Each artifact below is one Maven module under the com.dolby.optiview group.
ads-sdk-runtime — start here. The Android runtime: the Media3 / ExoPlayer player adapter, the overlay ad renderer, and Google Ad Manager pod serving. Depending on it brings ads-sdk and ads-sdk-core transitively.
ads-sdk-adapter-theoplayer — the player adapter for the OptiView Player (THEOplayer).
ads-sdk — the player-agnostic OptiViewAds orchestrator: configuration, session lifecycle, the event stream, and diagnostics.
ads-sdk-core — the portable core: the Break Manifest model, the PlayerAdapter contract, and the diagnostic code taxonomy.
ads-sdk-adapter-test-kit — the conformance test base for a custom PlayerAdapter.
The integration guide is at optiview.dolby.com.
+The player-agnostic orchestrator of the OptiView Ads SDK. OptiViewAds wires the core to a PlayerAdapter, runs the session lifecycle (startSession, endSession), emits the public event stream (OptiViewAdsEvent) and the diagnostics stream, and defines the seams the Android runtime implements (AdRenderer, ManifestSource, SchedulerTicker). Pure Kotlin/JVM; the Android-specific pieces live in ads-sdk-runtime.
The conformance test base for a custom PlayerAdapter. Extend PlayerAdapterConformanceTest in your test source set (testImplementation) to hold your adapter to the same contract the bundled adapters pass: event forwarding, state mirroring, seeking, and cleanup on destroy.
The PlayerAdapter for the OptiView Player (THEOplayer) on Android. THEOplayerAdapter wraps the Player of a THEOplayerView the app owns, so the SDK can drive THEOplayer-based playback exactly like Media3 through ExoPlayerAdapter. THEOplayer itself is not bundled: the app provides its own THEOplayer dependency and license.
The portable core of the OptiView Ads SDK: pure Kotlin/JVM with no Android or player dependencies. It holds the types the rest of the SDK is expressed in — the Break Manifest model, the PlayerAdapter contract a content player is driven through, the ad-insertion and delivery modes, and the diagnostic code taxonomy. Integrators rarely depend on it directly; ads-sdk-runtime and ads-sdk bring it transitively.
The Android runtime of the OptiView Ads SDK, and the artifact an app depends on: ExoPlayerAdapter (the PlayerAdapter for Media3 / ExoPlayer), OverlayAdRenderer (ad playback in an overlay above the content player, including pause ads), GamStreamManager (Google Ad Manager pod serving through the IMA SDK) and VastAdManager (client-side VAST playout). Depends on ads-sdk and ads-sdk-core.