Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Media buttons in notification #216

Closed
at-oliverapps opened this issue Dec 4, 2022 · 23 comments
Closed

Media buttons in notification #216

at-oliverapps opened this issue Dec 4, 2022 · 23 comments

Comments

@at-oliverapps
Copy link

i would like to know how to customize the notification in media 3 like shown in pictures below

Expected behavior how it was before with PlayerNotificationManager

Screenshot_20221204_222500_One UI Home
Screenshot_20221204_222521_Radio (eta)

how it is now with media3
Screenshot_20221204_222204_Radio (eta)
Screenshot_20221204_222435_Radio (eta)

@marcbaechinger
Copy link
Contributor

PlayerNotificationManager does not work together with Android 13 out of the box. If you want to customize the notification to get a notification as above you can implement a CustomLayout that defines the custom commands that should be displayed on the mini player/media notification.

There is issue #38 that explains how a custom layout can be done that provides a notification across all API levels.

You can use DefaultMediaNotificationProvider to tune the look of the notification on API levels lower than 33 (see JavaDoc and please see #213 that is fixed on the main branch).

You may want to consult the Android 13 documentation on how custom actions are used to layout the new miniplayer.
https://developer.android.com/about/versions/13/behavior-changes-13#playback-controls

@at-oliverapps
Copy link
Author

hello Marc thanks for reaching back to me
first 2 pics is with Media3 and below is PlayerNotificationManager
im using media3 now and I like it but I have these problems

I tried searching around and I can't seem to figure out how to make it work on my own I even looked at the documentation and in sourcecode for DefaultMediaNotificationProvider
its described how to get it appear in miniplayer but not how to make ( PREV : PLAY_PAUSE : NEXT ) appear in miniplayer below android 13

and can't figure out to replace (play next prev) icons in android 13 I know Spotify did it and it works for me below android 13
is it how it is in android 13+

@marcbaechinger
Copy link
Contributor

marcbaechinger commented Dec 6, 2022

EDIT: Since this comment was written, Media3 has introduced an API throught the media notification controller, which is now the preferred way to remove player commands for the media notification. Using a ForwardingPlayer is discouraged as it has the disadvantage to remove the command on the player level and hence for all controllers.

See also Android Media Controls.


Yeah, it's complicated. Please accept my apologies that this is not documented properly yet. We need to provide this asap because it is complicated. I added the documentation candidate labels to express this.

Let me try to give an overview/introduction:

  1. All screenshots above are mini players based on the actions that are added to the notification. These are PendingIntent that will be sent to the service when tapped. These kind of notifications are displayed on all devices with Android 12 and earlier. They are also shown like this for apps that are running on an Android 13 device but still have the targetSdk set to below 33. I think this is the case for your app, that's why even on Android 13 it is handled like for Android 12 and before.

  2. For all these cases (Android 12 and earlier and apps with targetSdk below 33), by default, the DefaultMediaNotificationProvider adds all the player commands first and then the custom layout. I think that's how you end up with this:

image

You can change the order of the actions by creating your own MediaNotificationProvider that is a sublcass of DefaultMediaNotifcationProvider and then override getMediaButtons(). However, there is a bug #213 that is fixed on the main branch but not yet release. This prevents you from subclassing the DefaultMediaNotificationProvider with the current released version I'm afraid.

With the fix of #213 this lets you create the notifications for API level <33 as you like I think.

  1. On Android 13 and with targetSdk=33, the mini player is based on the actions and custom actions that are present in the PlaybackStateCompat of the media session as opposed to the actions of the notification. It looks like this (note the big play/pause button)

image

Because it is not based on the notification but on the PlaybackStateCompat the order of the elements is different. By default the custom actions are placed to the right (see the crossed arrow shuffle icon to the right which is a custom command that is added to the CustomLayout as described in #38).

It's possible to hide the skip previous and skip next button by removing the available commands Player.COMMAND_SEEK_TO_PREVIOUS and Player.COMMAND_SEEK_TO_NEXT from the player that is used when building the MediaSession in Media3:

val player =
      ExoPlayer.Builder(this)
        .setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true)
        .build()

val forwardingPlayer =
      object : ForwardingPlayer(player) {
        override fun getAvailableCommands(): Player.Commands {
          return super.getAvailableCommands()
                  .buildUpon()
                  .remove(COMMAND_SEEK_TO_PREVIOUS)
                  .remove(COMMAND_SEEK_TO_NEXT)
                  .build()
        }
      }
MediaSession.Builder(context, forwardingPlayer)
    .build()

Now, the skip previous and the skip next button would not be displayed in the mini player. Instead the custom actions are placed at these positions. So in the screenshot above the shuffle icon would be at the position of the skip previous button. With this we can for instance provide three custom commands in the CustomLayout like:

[[rewind 30s], [ffwd 30s], [shuffle]]

Now, the rewind 30s is to the left of the seek bar, ffwd 30s is to the right of the seekbar, and all the other custom commands follow to the right.

EDIT: I don't think this last section is correct, sorry. This is currently not supported with Media3

However, some apps probably do not want that. So we can advice the mini player to simply space out the skip to previous/skip to next buttons and leave them empty, and put the custom command as the are in the screenshot above (usually only one is displayed). To signal this an app needs to set some session extras right after building the session:

val sessionExtras = Bundle()
sessionExtras.putBoolean(MediaConstants.EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV, true);
sessionExtras.putBoolean(MediaConstants.EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT, true);
mediaSession.setSessionExtras(sessionExtras)

@PaulWoitaschek
Copy link
Contributor

I'm also having a really hard time figuring this out.
I'm developing an audiobook player so the hard fast forward / rewind do not make sense at all.

However I still need them to be supported because if for example a user presses next / previous through a bluetooth headset gesture I need to handle that as a fast forward / rewind instead.

I achieved that by overwriting the commands in my wrapping player:

  override fun seekToPreviousMediaItem() {
    seekBack()
  }

  override fun seekToPrevious() {
    seekBack()
  }

  override fun seekToNext() {
    seekForward()
  }

  override fun seekToNextMediaItem() {
    seekForward()
  }

Setting EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV does / NEXT does not seem to have any effect.

Right now I could get two things to work:

  1. Advertise the default commands and overwriting their actions. This has the disadvantage that in the Android 13 Notification, the previous / next icons are shown instead of the fast forward / rewind icons.
  2. Remove the next / previous from the available commands. This leads to my custom fast forward / rewind being shown. So from the UI everything is perfect. This however now breaks the ability to control the fast forward / rewind using bluetooth headset taps.

Is there any way to fix this?

@maknon
Copy link

maknon commented Dec 19, 2022

val player =
      ExoPlayer.Builder(this)
        .setAudioAttributes(AudioAttributes.DEFAULT, /* handleAudioFocus= */ true)
        .build()

val forwardingPlayer =
      object : ForwardingPlayer(player) {
        override fun getAvailableCommands(): Player.Commands {
          return super.getAvailableCommands()
                  .buildUpon()
                  .remove(COMMAND_SEEK_TO_PREVIOUS)
                  .remove(COMMAND_SEEK_TO_NEXT)
                  .build()
        }
      }
MediaSession.Builder(context, forwardingPlayer)
    .build()

Now, the skip previous and the skip next button would not be displayed in the mini player

if i have more than one MediaItem, the button is displayed but do nothing if clicked when trying to use this code. is this a bug or an intended behavior ?

@brabebhin
Copy link

brabebhin commented Jan 19, 2023

I managed to obtain the first expected screenshot by using this media notification builder implementation. My aim was to have all 3 buttons (skip previous, play/pause, skip next) shown in compact mode on both android 12 and 13, as shown in the first screenshot

My guess is that further customization can be done with addNotificationActions. Maybe this can further help people who also run into this issue.

class MediaNotificationBuilder(val context: Context) : DefaultMediaNotificationProvider(context) {

override fun addNotificationActions(
    mediaSession: MediaSession,
    mediaButtons: MutableList<CommandButton>,
    builder: NotificationCompat.Builder,
    actionFactory: MediaNotification.ActionFactory
): IntArray {

    val skipPreviousCommandButton = CommandButton.Builder().setPlayerCommand(COMMAND_SEEK_TO_PREVIOUS).setEnabled(true).setIconResId(androidx.media3.ui.R.drawable.exo_ic_skip_previous)
        .setExtras(Bundle().apply { putInt("androidx.media3.session.command.COMPACT_VIEW_INDEX", 0)}).build();

    val playCommandButton = CommandButton.Builder().setPlayerCommand(COMMAND_PLAY_PAUSE).setEnabled(true).setIconResId(if(mediaSession.player.isPlaying) androidx.media3.ui.R.drawable.exo_icon_pause else androidx.media3.ui.R.drawable.exo_icon_play)
        .setExtras(Bundle().apply { putInt("androidx.media3.session.command.COMPACT_VIEW_INDEX", 1)}).build();

    val skipNextCommandButton = CommandButton.Builder().setPlayerCommand(COMMAND_SEEK_TO_NEXT).setEnabled(true).setIconResId(androidx.media3.ui.R.drawable.exo_ic_skip_next)
        .setExtras(Bundle().apply { putInt("androidx.media3.session.command.COMPACT_VIEW_INDEX", 2)}).build();

    mediaButtons.clear()
    mediaButtons.add(skipPreviousCommandButton)
    mediaButtons.add(playCommandButton)
    mediaButtons.add(skipNextCommandButton)

    return super.addNotificationActions(mediaSession, mediaButtons, builder, actionFactory)
}

}

@marcbaechinger
Copy link
Contributor

Thanks for the snippet @brabebhin

If you override DefaultMediaNotificationProvider.getMediaButtons(...) and then return that list of buttons that you create above, would that be the same? The list would then be the argument mediaButtons in addNotificationActions(...). That's how the API was designed. Sorry for this not being documented yet besides the JavaDoc. Documentation work has been started and is on it's way.

@brabebhin
Copy link

brabebhin commented Jan 19, 2023

This is for beta2. In beta3 it is no longer possible to derive DefaultMediaNotificationProvider, as I just tried right now.

The problem with getMediaButtons (assuming the inability to override is another bug) is that you can't get to know which is the playback state of the player. You could theoretically pass the player instance to the constructor of the provider, but that is also ugly.

And since addNotificationActions allow you to override that list that you get as parameter, this is how I got it to work properly. In fact, I could simply create a new list there with the buttons and add them to the new list instead of using the one passed as parameter, but I was too lazy to do it.

My sugestions:

Pass the session instance that you get in addNotificationActions to getMediaButtons as well. This allows access to the player instance and allows better customization.
Make DefaultMediaNotificationProvider constructors public again, to allow overriding.
Make the list of media actions that you get in addNotificationActios immutable, to clarify the usage of the API.

You should regard documentation as an overhead. Make the API more intuitive by using the tools available to simply guide developers on the right path.
E.G. Documentation says the constructor is public, but in reality it is not.

@marcbaechinger
Copy link
Contributor

Yes, sorry, my bad. The public constructors are already added in the main branch and this will be part of the next release that we are currently preparing (see #213).

I mark this issue as a bug to add the session like for addNotificationActions(..).

christosts pushed a commit that referenced this issue Jan 23, 2023
Issue: #216
#minor-release
PiperOrigin-RevId: 503406474
christosts pushed a commit that referenced this issue Jan 31, 2023
Issue: #216
#minor-release
PiperOrigin-RevId: 503406474
(cherry picked from commit e690802)
guoen21 added a commit to DiceTechnology/androidx-media that referenced this issue Jun 22, 2023
* Reorder some release notes in other sections.

#minor-release

PiperOrigin-RevId: 490224795
(cherry picked from commit fa531b79249e5435af719bfbe168b999b5032b47)

* Fix compilation error in ffmpeg JNI layer

PiperOrigin-RevId: 490263003
(cherry picked from commit a9be38a339161c9a286c496ba48cdde1d1db5fdc)

* Changed decoder list sort to order by functional support of format

Added new method to check if codec just functionally supports a format.
Changed getDecoderInfosSortedByFormatSupport to use new function to
order by functional support. This allows decoders that only support
functionally and are more preferred by the MediaCodecSelector to keep
their preferred position in the sorted list.

Unit tests included
-Two MediaCodecVideoRenderer tests that verify hw vs sw does not have an
effect on sort of the decoder list, it is only based on functional
support.

Issue: google/ExoPlayer#10604
PiperOrigin-RevId: 487779284
(cherry picked from commit fab66d972ef84599cdaa2b498b91f21d104fbf26)

* Update targetSdkVersion of demo session app to appTargetSdkVersion

PiperOrigin-RevId: 488884403
(cherry picked from commit cfe36af8478e78dd6e334298bcee425c61a9ba2a)

* Add bundling exclusions with unit tests

The exclusion will be used in a follow-up CL when sending PlayerInfo updates.

#minor-release

PiperOrigin-RevId: 488939258
(cherry picked from commit bae509009bd62554876ecb7485708e50af4eaa2a)

* Fix NPE when listener is not set

PiperOrigin-RevId: 488970696
(cherry picked from commit f3ed9e359dfdff2a99bf8766ffceb59a93d1bc93)

* Add setPlaybackLooper ExoPlayer builder method

The method allows clients to specify a pre-existing thread
to use for playback. This can be used to run multiple ExoPlayer
instances on the same playback thread.

PiperOrigin-RevId: 488980749
(cherry picked from commit e1fe3120e29a66ac2dcde6e9960756197bac6444)

* Load bitmaps for `MediaBrowserCompat`.

* Transforms the `ListenableFuture<LibraryResult<MediaItem>>` and `ListenableFuture<LibraryResult<List<MediaItem>>>` to `ListenableFuture<MediaBrowserCompat.MediaItem>` and `ListenableFuture<List<MediaBrowserCompat.MediaItem>>`, and the result will be sent out when `ListenableFuture` the `MediaBrowserCompat.MediaItem` (or the list of it) is fulfilled.
* Add `artworkData` to the tests in `MediaBrowserCompatWithMediaLibraryServiceTest`.

PiperOrigin-RevId: 489205547
(cherry picked from commit 4ce171a3cfef7ce1f533fdc0b7366d7b18ef44d1)

* Mark broadcast receivers as not exported

They are called from the system only and don't need to be exported
to be visible to other apps.

PiperOrigin-RevId: 489210264
(cherry picked from commit 22ccc1a1286803868970fb2b1eafe63e9c669a5c)

* Throw exception if a released player is passed to TestPlayerRunHelper

I considered moving this enforcement inside the ExoPlayerImpl
implementation, but it might lead to app crashes in cases that apps
(incorrectly) call a released player, but it wasn't actually causing a
problem.

PiperOrigin-RevId: 489233917
(cherry picked from commit cba65c8c61122c5f0a41bd95a767002e11a1bae4)

* Add additional codecs to the eosPropagationWorkaround list.

Issue: google/ExoPlayer#10756
PiperOrigin-RevId: 489236336
(cherry picked from commit d1b470e4cc26a15525b583d1953529c8ec73a950)

* Pass correct frame size for passthrough playback

When estimating the AudioTrack min buffer size, we must use a PCM
frame of 1 when doing direct playback (passthrough). The code was
passing -1 (C.LENGTH_UNSET).

PiperOrigin-RevId: 489238392
(cherry picked from commit 07d25bf41d9fa4d81daade6787a9b15682e9cf1f)

* Add remaining state and getters to SimpleBasePlayer

This adds the full Builders and State representation needed to
implement all Player getter methods and listener invocations.

PiperOrigin-RevId: 489503319
(cherry picked from commit 81918d8da7a4e80a08b65ade85ecb37c995934e7)

* Do not require package visibility when connecting to a Media3 session

When we currently call SessionToken.createSessionToken with a legacy
token, we call the package manager to get the process UID. This
requires visiblity to the target package, which may not be available
unless the target runs a service known to the controller app.

However, when connecting to a Media3, this UID doesn't have to be
known, so we can move the call closer to where it's needed to
avoid the unncessary visibility check.

In addition, a legacy session may reply with unknown result code
to the session token request, which we should handle as well.

One of the constructor can be removed since it was only used from
a test.

PiperOrigin-RevId: 489917706
(cherry picked from commit 2fd4aac310787d1a57207b5142a0ab08d5e1a2a5)

* Add `set -eu` to all shell scripts

These flags ensure that any errors cause the script to exit (instead of
just carrying on) (`-e`) and that any unrecognised substitution variables
cause an error instead of silently resolving to an empty string (`-u`).

Issues like Issue: google/ExoPlayer#10791 should be more quickly resolved with
`set -e` because the script will clearly fail with an error like
`make: command not found` which would give the user a clear pointer
towards the cause of the problem.

#minor-release

PiperOrigin-RevId: 490001419
(cherry picked from commit 45b8fb0ae1314abdc5b0364137622214ac8e5b98)

* Do not require package visibility when obtaining SessionTokens

The only reason this is required at the moment is to set the
process UID field in the token, that is supposed to make it easier
for controller apps to identify the session. However, if this
visibility is not provided, it shouldn't stop us from creating
the controller for this session.

Also docuement more clearly what UID means in this context.

PiperOrigin-RevId: 490184508
(cherry picked from commit c41a5c842080a7e75b9d92acc06d583bd20c7abb)

* Add `DefaultExtractorsFactory.setTsSubtitleFormats`

ExoPlayer is unable to detect the presence of subtitle tracks in some
MPEG-TS files that don't fully declare them. It's possible for a
developer to provide the list instead, but doing so is quite awkward
without this helper method. This is consistent for how
`DefaultExtractorsFactory` allows other aspects of the delegate
`Extractor` implementations to be customised.

* Issue: google/ExoPlayer#10175
* Issue: google/ExoPlayer#10505

#minor-release

PiperOrigin-RevId: 490214619
(cherry picked from commit ff48faec5f9230355907a8be24e44068ec294982)

* Reorder some release notes in other sections.

PiperOrigin-RevId: 490224795
(cherry picked from commit fa531b79249e5435af719bfbe168b999b5032b47)

* Load bitmaps for `MediaSessionCompat.QueueItem`.

When receiving the `onTimelineChanged` callback, we convert the timeline to the list of `QueueItem`s, where decoding a bitmap is needed for building each of the `QueueItem`s. The strategy is similar to what we did in <unknown commit> for list of `MediaBrowserCompat.MediaItem` - set the queue item list until the bitmaps decoding for all the `MediaItem`s are completed.

PiperOrigin-RevId: 490283587
(cherry picked from commit 8ce1213ddddb98e0483610cfeaeba3daa5ad9a78)

* Migrate BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS to Media3

PiperOrigin-RevId: 490376734
(cherry picked from commit 1803d1cdb8cf429c3d0a3fdbbecbad25145db8c4)

* Add helper method to convert platform session token to Media3 token

This avoids that apps have to depend on the legacy compat support
library when they want to make this conversion.

Also add a version to both helper methods that takes a Looper to
give apps the option to use an existing Looper, which should be
much faster than spinning up a new thread for every method call.

Issue: androidx/media#171
PiperOrigin-RevId: 490441913
(cherry picked from commit 03f0b53cf823bb4878f884c055b550b52b9b57ab)

* Merge pull request #10786 from TiVo:p-aacutil-test-impl

PiperOrigin-RevId: 490465182
(cherry picked from commit a32b82f7bd14161b4ba204db28ca842f1dd0bb12)

* Call future listener on the same handler that created the controller

The direct executor is not the proper way to determine on what thread to run the
`Future.Listener` and the `MediaControllerCreationListener` because the listener
may call the controller passed as argument which must happen on the same thread
that built the controller. This change makes sure this is the case.

PiperOrigin-RevId: 490478587
(cherry picked from commit 68908be18d0a46478be05ad406a5027c15c38723)

* Exclude tracks from `PlayerInfo` if not changed

This change includes a change in the `IMediaController.aidl` file and needs
to provide backwards compatibility for when a client connects that is of an older or
newer version of the current service implementation.

This CL proposes to create a new AIDL method `onPlayerInfoChangedWithExtensions`
that is easier to extend in the future because it does use an `Bundle` rather than
primitives. A `Bundle` can be changed in a backward/forwards compatible way
in case we need further changes.

The compatibility handling is provided in `MediaSessionStub` and `MediaControllerStub`. The approach is not based on specific AIDL/Binder features but implemented fully in application code.

Issue: androidx/media#102
#minor-release
PiperOrigin-RevId: 490483068
(cherry picked from commit 3d8c52f28d5d3ef04c14868e15036563a9fc662d)

* Misc fix in gradle build file

Issue: androidx/media#209

#minor-release

PiperOrigin-RevId: 490492223
(cherry picked from commit 2424ee77926923fc1bf690e7e623ff9d57b9a200)

* Handle the bitmap loading result with applicationHandler

Before this change, the bitmap loading result with mainHandler, in which we set the metadata to `MediaSessionCompat`. However, the `MediaSessionCompat` is not thread safe, all calls should be made from the same thread. In the other calls to `MediaSessionCompat`, we ensure that they are on the application thread (which may be or may not be main thread), so we should do the same for `setMetadata` when bitmap arrives.

Also removes a comment in `DefaultMediaNotificationProvider` as bitmap request caching is already moved to CacheBitmapLoader.

PiperOrigin-RevId: 490524209
(cherry picked from commit 80927260fd46413b7d1efafed72360b10049af2a)

* Parse and set `peakBitrate` for Dolby TrueHD(AC-3) and (E-)AC-3

#minor-release

PiperOrigin-RevId: 490527831
(cherry picked from commit 76df06a7a364c580dfe07d9f069237cd77c5174c)

* Rollback of https://github.com/androidx/media/commit/76df06a7a364c580dfe07d9f069237cd77c5174c

*** Original commit ***

Parse and set `peakBitrate` for Dolby TrueHD(AC-3) and (E-)AC-3

#minor-release

***

PiperOrigin-RevId: 490570517
(cherry picked from commit 427329175e87a7f3173791c59e6c2d4c4ed8dea4)

* Rollback of https://github.com/androidx/media/commit/427329175e87a7f3173791c59e6c2d4c4ed8dea4

*** Original commit ***

Rollback of https://github.com/androidx/media/commit/76df06a7a364c580dfe07d9f069237cd77c5174c

*** Original commit ***

Parse and set `peakBitrate` for Dolby TrueHD(AC-3) and (E-)AC-3

#minor-release

***

***

PiperOrigin-RevId: 490707234
(cherry picked from commit 82711630ed1afbe7417aad95244a91135e24c27f)

* Use `ParsableBitArray` instead of `ParsableByteArray`

To avoid complicated bit shifting and masking. Also makes the code more readable.

PiperOrigin-RevId: 490749482
(cherry picked from commit 3d31e094a9e802354dce2f3dc5f33062f7624248)

* Convert bitrates to bps before setting it

Format expects the values of `averageBitrate` and `peakBitrate` in bps and the value fetched from AC3SpecificBox and EC3SpecificBox is in kbps.

PiperOrigin-RevId: 490756581
(cherry picked from commit 4066970ce7292642794f4a3954f8d0fde78dd310)

* Remove flakiness from DefaultAnalyticsCollectorTest

Our FakeClock generally makes sure that playback tests are fully
deterministic. However, this fails if the test uses blocking waits
with clock.onThreadBlocked and where relevant Handlers are created
without using the clock.

To fix the flakiness, we can make the following adjustments:
 - Use TestExoPlayerBuilder instead of legacy ExoPlayerTestRunner
   to avoid onThreadBlocked calls. This also makes the tests more
   readable.
 - Use clock to create Handler for FakeVideoRenderer and
   FakeAudioRenderer. Ideally, this should be passed through
   RenderersFactory, but it's too disruptive given this is a
   public API.
 - Use clock for MediaSourceList and MediaPeriodQueue update
   handler.

PiperOrigin-RevId: 490907495
(cherry picked from commit 6abc94a8b7180979c520fc581310b87bf297b1bb)

* Clean up javadoc on `Metadata.Entry.populateMediaMetadata`

Remove self-links, and remove section that is documenting internal
ordering behaviour of
[`SimpleBasePlayer.getCombinedMediaMetadata`](https://github.com/google/ExoPlayer/blob/bb270c62cf2f7a1570fe22f87bb348a2d5e94dcf/library/common/src/main/java/com/google/android/exoplayer2/SimpleBasePlayer.java#L1770)
rather than anything specifically about this method.

#minor-release

PiperOrigin-RevId: 490923719
(cherry picked from commit a6703285d0d1bedd946a8477cb68c46b1a097b09)

* Ensure messages sent on a dead thread don't block FakeClock execution

FakeClock keeps an internal list of messages to be executed to
ensure deterministic serialization. The next message from the list
is triggered by a separate helper message sent to the real Handler.
However, if the target HandlerThread is no longer alive (e.g. when
it quit itself during the message execution), this helper
message is never executed and the entire message execution chain
is stuck forever.

This can be solved by checking the return values of Hander.post or
Handler.sendMessage, which are false if the message won't be
delivered. If the messages are not delivered, we can unblock the
chain by marking the message as complete and triggering the next
one.

PiperOrigin-RevId: 491275031
(cherry picked from commit 8fcc06309323847b47ed8ab225cd861335448d36)

* Merge pull request #10799 from OxygenCobalt:id3v2-multi-value

PiperOrigin-RevId: 491289028
(cherry picked from commit b81d5f304e2f5fc55577e31c31ff6df5ce7d0ef5)

* Split up `Id3DecoderTest` methods

It's clearer if each test method follows the Arrange/Act/Assert pattern

PiperOrigin-RevId: 491299379
(cherry picked from commit fc5d17832f90f36eb30ee0058204d110e27adcc9)

* Remove impossible `UnsupportedEncodingException` from `Id3Decoder`

The list of charsets is already hard-coded, and using `Charset` types
ensures they will all be present at run-time, hence we will never
encounter an 'unsupported' charset.

PiperOrigin-RevId: 491324466
(cherry picked from commit 5292e408a6fd000c1a125519e22a7c18460eed59)

* Merge pull request #10776 from dongvanhung:feature/add_support_clear_download_manager_helpers

PiperOrigin-RevId: 491336828
(cherry picked from commit 3581ccde29f0b70b113e38456ff07167267b0ad9)

* Bump cast sdk version and remove workaround for live duration

The fix for b/171657375 (internal) has been shipped with 21.1.0 already
(see https://developers.google.com/cast/docs/release-notes#august-8,-2022).

PiperOrigin-RevId: 491583727
(cherry picked from commit 835d3c89f2099ca66c5b5f7af686eace1ac17eb8)

* Add configuration to support OPUS offload

To support OPUS offload, we need to provide a few configuration values
that are currently not set due to the lack of devices supporting
OPUS offload.

PiperOrigin-RevId: 491613716
(cherry picked from commit 568fa1e1fa479fd1659abf1d83d71e01227ab9cf)

* Use audio bitrate to calculate AudioTrack min buffer in passthrough

Use the bitrate of the audio format (when available) in
DefaultAudioSink.AudioTrackBufferSizeProvider.getBufferSizeInBytes() to
calculate accurate buffer sizes for direct (passthrough) playbacks.

#minor-release

PiperOrigin-RevId: 491628530
(cherry picked from commit d12afe0596b11c473b242d6389bc7c538a988238)

* Add public constructors to `DefaultMediaNotificationProvider`

Issue: androidx/media#213

Without a public constructor, it is not possible to extend this class and override its method.

PiperOrigin-RevId: 491673111
(cherry picked from commit f3e450e7833bbc62237c1f24f9a1f6c4eed21460)

* Use the artist as the subtitle of the legacy media description

The Bluetooth AVRCP service expects the metadata of the item currently
being played to be in sync with the corresponding media description in
the active item of the queue. The comparison expects the metadata values
of `METADATA_KEY_TITLE` and `METADATA_KEY_ARTIST` [1] to be equal to the
`title` and `subtitle` field of the `MediaDescription` [2] of the
corresponding queue item.

Hence we need to populate the media description accordingly to avoid the
BT service to delay the update for two seconds and log an exception.

[1] https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/android/app/src/com/android/bluetooth/audio_util/helpers/Metadata.java;l=120
[2] https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java;l=258

Issue: androidx/media#148
PiperOrigin-RevId: 491877806
(cherry picked from commit 2a07a0b44582782b09a96b5819e9899308e79545)

* Rename SimpleBasePlayer.PlaylistItem to MediaItemData

This better matches the terminology we use elsewhere in the Player
interface, where items inside the playlist are referred to as
"media item" and only the entire list is called "playlist".

PiperOrigin-RevId: 491882849
(cherry picked from commit ff7fe222b83c55c93cc9ee1a3763a11473168ece)

* Decomission ControllerInfoProxy in favor of ControllerInfo.

This CL makes it possible to create a media3 ControllerInfo in test code, which is needed to test several aspects of a media3-based media app. It does this by exposing a test-only static factory method. This is a hacky low-effort approach; a better solution could be to split ControllerInfo up into a public interface that was exposed to client logic, and that they could extend, and a package-private implementation with internal fields like the callback. That's a much bigger change, however.

PiperOrigin-RevId: 491978830
(cherry picked from commit 69093db7f5889037a3b55e3d1a7242c31ce62f2f)

* Parse and set bitrates in `Ac3Reader`

PiperOrigin-RevId: 492003800
(cherry picked from commit c7aa54cb411e485c2c17e630779d9e27d758a550)

* Add media type to MediaMetadata

This helps to denote what type of content or folder the metadata
describes.

PiperOrigin-RevId: 492123690
(cherry picked from commit 32fafefae81e0ab6d3769152e584981c1a62fc60)

* Add support for most setters in SimpleBasePlayer

This adds the forwarding logic for most setters in SimpleExoPlayer
in the same style as the existing logic for setPlayWhenReady.

This change doesn't implement the setters for modifying media items,
seeking and releasing yet as they require additional handling that
goes beyond the repeated implementation pattern in this change.

PiperOrigin-RevId: 492124399
(cherry picked from commit f007238745850791f8521e61f6adaf8ed2467c45)

* Merge pull request #10750 from Stronger197:subrip_utf_16

PiperOrigin-RevId: 492164739
(cherry picked from commit a9191418051a19681ddf884163ac5553871ec658)

* Split SubripDecoder and ParsableByteArray tests

In some cases we split a test method, and in other cases we just add
line breaks to make the separation between arrange/act/assert more
clear.

PiperOrigin-RevId: 492182769
(cherry picked from commit e4fb663b23e38eb6e41b742681bf80b872baad24)

* Reduce log output for failing bitmap loads

Do not log the exception stack traces raised by the BitmapLoader when a
bitmap fails to load, e.g. when the artwork's URI scheme is not
supported by the SimpleBitmapLoader. The logs are kept in place but only
a single line is printed.

#minor-release

PiperOrigin-RevId: 492191461
(cherry picked from commit f768ff970ca15483bcb02c1cf41746b67ec8c3ac)

* Stop service when app is terminated while the player is paused

If the service ever has been started but is not in the foreground, the
service would be terminated without calling onDestroy(). This is because
when onStartCommand returns START_STICKY [1], the app takes the
responsibility to stop the service.

Note that this change interrupts the user journey when paused, because the
notification is removed. Apps can implement playback resumption [2] to give
the user an option to resume playback after the service has been terminated.

[1] https://developer.android.com/reference/android/app/Service#START_STICKY
[2] https://developer.android.com/guide/topics/media/media-controls#supporting_playback_resumption

Issue: androidx/media#175
#minor-release
PiperOrigin-RevId: 492192690
(cherry picked from commit 6a5ac19140253e7e78ea65745914b0746e527058)

* Write media type with a custom key to legacy components.

This allows legacy media controllers and browsers to access this
information and legacy sessions and browser services to set this
information.

PiperOrigin-RevId: 492414716
(cherry picked from commit ca4c6efdb7fdb50cef116d26360b79ed75a6401e)

* Added cancellation check for MediaBrowserFuture in demo session app

When app is deployed with device's screen being off, MainActivity's onStart is called swiftly by its onStop. The onStop method cancels the browserFuture task which in turn "completes" the task. Upon task "completion", pushRoot() runs and then throws error as it calls get() a cancelled task.

PiperOrigin-RevId: 492416445
(cherry picked from commit 64603cba8db9fbd9615e19701464c4d0734a86dc)

* Removed ExoPlayer specific states from SimpleBasePlayer

PiperOrigin-RevId: 492443147
(cherry picked from commit 2fd38e3912960c38d75bce32cc275c985a2722c1)

* Fix `TextRenderer` exception when a subtitle file contains no cues

Discovered while investigating Issue: google/ExoPlayer#10823

Example stack trace with the previous code (I added the index value for
debugging):

```
playerFailed [eventTime=44.07, mediaPos=44.01, window=0, period=0, errorCode=ERROR_CODE_FAILED_RUNTIME_CHECK
  androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:635)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loopOnce(Looper.java:202)
      at android.os.Looper.loop(Looper.java:291)
      at android.os.HandlerThread.run(HandlerThread.java:67)
  Caused by: java.lang.IllegalArgumentException: index=-1
      at androidx.media3.common.util.Assertions.checkArgument(Assertions.java:55)
      at androidx.media3.extractor.text.webvtt.WebvttSubtitle.getEventTime(WebvttSubtitle.java:62)
      at androidx.media3.extractor.text.SubtitleOutputBuffer.getEventTime(SubtitleOutputBuffer.java:56)
      at androidx.media3.exoplayer.text.TextRenderer.getCurrentEventTimeUs(TextRenderer.java:435)
      at androidx.media3.exoplayer.text.TextRenderer.render(TextRenderer.java:268)
      at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1008)
      at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:509)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loopOnce(Looper.java:202)
      at android.os.Looper.loop(Looper.java:291)
      at android.os.HandlerThread.run(HandlerThread.java:67)
]
```

#minor-release

PiperOrigin-RevId: 492464180
(cherry picked from commit 33bbb9511a9ac6ad6495d4e264f8e248c4342763)

* Fix `ExoPlayerTest` to use `C.TIME_UNSET` instead of `C.POSITION_UNSET`

This inconsistency was exposed by an upcoming change to deprecate
`POSITION_UNSET` in favour of `INDEX_UNSET` because position is an
ambiguous term between 'byte offset' and 'media position', as shown
here.

PiperOrigin-RevId: 492470241
(cherry picked from commit 2650654dd0d0654fc4cca67b0d3347d88431fa4e)

* Fix threading of onFallbackApplied callback

The callback is currently triggered on the ExoPlayer playback thread
instead of the app thread that added the listener.

PiperOrigin-RevId: 492474405
(cherry picked from commit 634c6161f11f33b960023350d418bd3493f5a4b9)

* Add javadoc links to README files

Fix some other link titles and destinations spotted along the way.

#minor-release

PiperOrigin-RevId: 493276172
(cherry picked from commit 636a4a8538ccfb235eeca7d9131d4b5d4d95e9aa)

* Support release in SimpleBasePlayer

This adds support for the release handling. To align with the
established behavior in ExoPlayer, the player can only call
listeners from within the release methods (and not afterwards)
and automatically enforces an IDLE state (without listener call)
in case getters of the player are used after release.

PiperOrigin-RevId: 493543958
(cherry picked from commit 4895bc42ff656ba77b604d8c7c93cba64733cc7a)

* Replace MediaMetadata folderType by isBrowsable

The folder type has a mix of information about the item. It shows
whether the item is browsable (type != FOLDER_TYPE_NONE) and
which Bluetooth folder type to set for legacy session information.

It's a lot clearer to split this into a boolean isBrowsable and
use the existing mediaType to map back to the bluetooth folder type
where required.

folderType is not marked as deprecated yet as this would be an API
change, which will be done later.

PiperOrigin-RevId: 493544589
(cherry picked from commit ae8000aecaee725dea51a6ded06125884a5b8112)

* Remove debug timeout multiplier.

It looks like this was added accidentally in <unknown commit>.

PiperOrigin-RevId: 493834134
(cherry picked from commit 533f5288f4aec47a75357bf308907d1686ba493a)

* Clarify and correct allowed multi-threading for some Player methods

Some Player methods like getting the Looper and adding listeners
were always allowed to be called from any thread, but this is
undocumented. This change makes the threading rules of these
methods more explicit.

Removing listeners was never meant to be called from another thread
and we also don't support it safely because final callbacks may
be triggered from the wrong thread. To find potential issues, we
can assert the correct thread when releasing listeners.

Finally, there is a potential race condition when calling addListener
from a different thread at the same time as release, which may lead to
a registered listener that could receive callbacks after the player is
released.

PiperOrigin-RevId: 493843981
(cherry picked from commit 927b2d6a435a236bb5db7646cf6402557db893f6)

* Forward seek command details to seekTo method in BasePlayer

BasePlayer simplifies implementations by handling all the various
seek methods and forwarding to a single method that can then be
implemented by subclasses. However, this loses the information about
the concrete entry point used for seeking, which is relevant when
the subclass wants to verify or filter by Player.Command. This
can be improved by adding the command as a new parameter. Since
we have to change the method anyway, we can also incorporate the
boolean flag about whether the current item is repeated to avoid
the separate method.

PiperOrigin-RevId: 494948094
(cherry picked from commit ab6fc6a08d0908afe59e7cd17fcaefa96acf1816)

* Reset isLoading when calling SimpleBasePlayer.stop/release

isLoading is not allowed to be true when IDLE, so we have to set to
false when stopping in case it was set to true before.

PiperOrigin-RevId: 494975405
(cherry picked from commit 6e7de583bb42871267899776966575512152b111)

* Document the reason for defining private method `defaultIfNull`

PiperOrigin-RevId: 495004732
(cherry picked from commit 610e431c906d71fd684c5c7c8ff8a9aa171a55ef)

* Remove parameters with default values from bundle in `MediaItem`

This improves the time taken to construct PlayerInfo from bundle from ~600ms to ~450ms.

PiperOrigin-RevId: 495055355
(cherry picked from commit 395cf4debc52c9209377ea85a319d2e27c6533ce)

* Fix some release notes typos

PiperOrigin-RevId: 495262344
(cherry picked from commit c9e87f050303a78e39aa0c96eab48e30714f3351)

* Clear one-off events from state as soon as they are triggered.

This ensures they are not accidentally triggered again when
the state is rebuilt with a buildUpon method.

PiperOrigin-RevId: 495280711
(cherry picked from commit a1231348926b4a88a2a8cb059204c083e304f23f)

* Allow unset index and position values + remove period index

This simplifies some position tracking needs for an app implementing
SimpleBasePlayer.
 - The period index can always be derived from the media item index
   and the position. So there is no need to set it separately.
 - The media item index can be left unset in the State in case the app
   doesn't care about the value or wants to set it the default start
   index (e.g. while the playlist is still empty where UNSET is
   different from zero).
 - Similarly, we should allow to set the content position (and buffered
   position) to C.TIME_UNSET to let the app ignore it or indicate the
   default position explictly.

PiperOrigin-RevId: 495352633
(cherry picked from commit 545fa5946268908562370c29bd3e3e1598c28453)

* Remove parameters with `null` values from bundle in `MediaMetadata`

Improves the time taken to construct `playerInfo` from its bundle from ~450 ms to ~400 ms. Each `MediaItem` inside `Timeline.Window` contains `MediaMetadata` and hence is a good candidate for bundling optimisations. There already exists a test to check all parameters for null values when unset.

PiperOrigin-RevId: 495614719
(cherry picked from commit d11e0a35c114225261a8fe472b0b93d4a8a6b727)

* Use theme when loading drawables on API 21+

Issue: androidx/media#220
PiperOrigin-RevId: 495642588
(cherry picked from commit 22dfd4cb32fdb76ba10047f555c983490c27eb13)

* Rename `EMPTY_MEDIA_ITEM` to `PLACEHOLDER_MEDIA_ITEM`

The `MediaItem` instances in the following cases are not actually empty but acts as a placeholder. `EMPTY_MEDIA_ITEM` can also be confused with `MediaItem.EMPTY`.

PiperOrigin-RevId: 495843012
(cherry picked from commit 3e7f53fda77048731d22de0221b0520a069eb582)

* Clarify behavior for out-of-bounds indices and align implementations

Some Player methods operate relative to existing indices in the
playlist (add,remove,move,seek). As these operations may be issued
from a place with a stale playlist (e.g. a controller that sends
a command while the playlist is changing), we have to handle out-
of-bounds indices gracefully. In most cases this is already
documented and implemented correctly. However, some cases are not
documented and the existing player implementations don't handle
these cases consistently (or in some cases not even correctly).

PiperOrigin-RevId: 495856295
(cherry picked from commit a1954f7e0a334492ffa35cf535d2e6c4e4c9ca91)

* Check if codec still exists before handling tunneling events

The tunneling callbacks are sent via Handler messages and may be
handled after the codec/surface was changed or released.

We already guard against the codec/surface change condition by
creating a new listener and verifying that the current callback
happens for the correct listener instance, but we don't guard
against a released codec yet.

PiperOrigin-RevId: 495882353
(cherry picked from commit 49ccfd63834d8ee68ac8018c42172da05108b35a)

* Avoid sending periodic position updates while paused and not loading

The period updates were introduced to ensure the buffered position is
updated regularly and that any playback position drift is corrected.

None of these updates need to happen while the player is paused or
not loading and we can avoid the constant binder interactions.

PiperOrigin-RevId: 496329800
(cherry picked from commit 0749b05923dd733bb515920334a9aae6067a072f)

* Add playlist and seek operations to SimpleBasePlayer

These are the remaining setter operations. They all share the same
logic that handles playlist and/or position changes. The logic to
create the placeholder state is mostly copied from ExoPlayerImpl's
maskTimelineAndPosition and getPeriodPositonUsAfterTimelineChanged.

PiperOrigin-RevId: 496364712
(cherry picked from commit 5fa115641d5b45b106844f3e629372417eb100b1)

* Remove ellipsis from Player javadoc

PiperOrigin-RevId: 496377192
(cherry picked from commit f0696f95720418d3c95a72f1454f712a40e40b8d)

* Fix Dackka error due to param name mismatch

https://developer.android.com/reference/androidx/leanback/media/PlayerAdapter#seekTo(long)

#minor-release

PiperOrigin-RevId: 496378709
(cherry picked from commit aae6941981dfcfcdd46544f585335ff26d8f81e9)

* Remove TODO from `ControllerInfo` - the existing approach is fine

PiperOrigin-RevId: 496398934
(cherry picked from commit 14947539e53143e84f4453505a403fbe3625af5d)

* Add BitmapLoader injection in MediaController

Also clean up the strict mode violations of using `BitmapFactory.convertToByteArray` on the main thread.

PiperOrigin-RevId: 496422355
(cherry picked from commit d848d3358a67ce2439db7cf170eec7b8c3ecffbf)

* Clarify some Player command and method javadoc

#minor-release

PiperOrigin-RevId: 496661152
(cherry picked from commit 31e875b7a094963a9ef2a355ab1a4c6d7d3d9687)

* Document the relationship between Player methods and available commands

#minor-release

PiperOrigin-RevId: 496668378
(cherry picked from commit d8c964cfe65bef4693056b052802ac1bee3ec56e)

* Add error messages to correctness assertions in SimpleBasePlayer

Users of this class may run into these assertions when creating the
State and they need to check the source code to understand why
the State is invalid. Adding error messages to all our correctness
assertions helps to understand the root cause more easily.

PiperOrigin-RevId: 496875109
(cherry picked from commit 6c98f238e45d19a14041d58f5938f3399da04eb5)

* Fix recursive loop when registering controller visibility listeners

There are two overloads of this method due to a type 'rename' from
`PlayerControlView.VisibilityListener` to
`PlayerView.ControllerVisibilityListener`. Currently when you call one
overload it passes `null` to the other one (to clear the other listener).
Unfortunately this results in it clearing itself, because it receives
a null call back!

This change tweaks the documentation to clarify that the 'other'
listener is only cleared if you pass a non-null listener in. This solves
the recursive problem, and allows the 'legacy' visibility listener to be
successfully registered.

Issue: androidx/media#229

#minor-release

PiperOrigin-RevId: 496876397
(cherry picked from commit 4087a011e21aba2c27e3ae890f74a65812c6f4ce)

* Update migration script

Issue: google/ExoPlayer#10854
PiperOrigin-RevId: 496922055
(cherry picked from commit 50090e39273356bee9b8da6b2f4a4dba1206f9a8)

* Bump IMA SDK version to 3.29.0

Issue: google/ExoPlayer#10845
PiperOrigin-RevId: 496947392
(cherry picked from commit 63352e97e99cc6ab2e063906be63392ea8b984b3)

* Check `MediaMetadata` bundle to verify keys are skipped

Added another check in test to make sure we don't add keys to bundle for fields with `null` values.

PiperOrigin-RevId: 496948705
(cherry picked from commit 13c93a3dd693e86e6d5208aff45105000858363f)

* Optimise bundling for `AdPlaybackState` using `AdPlaybackState.NONE`

Did not do this optimisation for `AdPlaybackState.AdGroup` as its length is zero for `AdPlaybackState` with no ads.

No need to pass default values while fetching keys, which we always set in `AdPlaybackState.AdGroup.toBundle()`.

PiperOrigin-RevId: 496995048
(cherry picked from commit 7fc2cdbe1bdf9968a1e73a670e5e32454090e1bd)

* Fix order of playback controls in RTL layout

Issue: androidx/media#227

#minor-release

PiperOrigin-RevId: 497159283
(cherry picked from commit 80603427abbd0da09f21e381cc10a5d47fb6d780)

* Enable RTL support in the demo app

We might as well keep this enabled by default, rather than having to
manually toggle it on to investigate RTL issues like Issue: androidx/media#227.

PiperOrigin-RevId: 497159744
(cherry picked from commit 69583d0ac1fa1ab1a1e250774fc1414550625967)

* Remove player listener on the application thread of the player

PiperOrigin-RevId: 497183220
(cherry picked from commit fc22f89fdea4aad4819a59d4819f0857a5596869)

* Check bundles in `MediaItem` to verify keys are skipped

Added another check in each of these tests to make sure we don't add keys to bundle for fields with default values.

Also fixed comments of similar changes in `AdPlaybackStateTest` and `MediaMetadataTest`.

PiperOrigin-RevId: 499463581
(cherry picked from commit 0512164fdd570a2047f51be719aae75ebcbf9255)

* Optimise bundling for `Timeline.Window` and `Timeline.Period`

Improves the time taken to construct playerInfo from its bundle from ~400 ms to ~300 ms.

Also made `Timeline.Window.toBundle(boolean excludeMediaItem)` public as it was required to assert a condition in tests.

PiperOrigin-RevId: 499512353
(cherry picked from commit 790e27d929906a36438af5b42ef62a13e4719045)

* Throw a ParserException instead of a NullPointerException if the sample table (stbl) is missing a required sample description (stsd).

As per the javadoc for AtomParsers.parseTrack, ParserException should be "thrown if the trak atom can't be parsed."

PiperOrigin-RevId: 499522748
(cherry picked from commit d8ea770e9ba6eed0bdce0b359c54a55be0844fd3)

* Fix typo in `DefaultTrackSelector.Parameters` field

PiperOrigin-RevId: 499905136
(cherry picked from commit b63e1da861d662f02d9a5888aaefb4a1b3347e40)

* Initialise fields used for bundling as String directly

Initialising the fields as Integer and then getting a String on compute
time is slow. Instead we directly initialise these fields as String.
Improves the time taken in bundling PlayerInfo further to less than
200ms from ~300ms.

Also modified a test to improve productive coverage.

PiperOrigin-RevId: 500003935
(cherry picked from commit 578f2de48f795ad90aafdad645c62fcdbd686e0a)

* Update bandwidth meter estimates

PiperOrigin-RevId: 501010994
(cherry picked from commit 2c7e9ca8237e39bde686dd635699778aa8c6b96e)

* Add focusSkipButtonWhenAvailable to focus UI on ATV

For TV devices the skip button needs to have the focus to be accessible with
the remote control. This property makes this configurable while being set to
true by default.

PiperOrigin-RevId: 501077608
(cherry picked from commit 9882a207836bdc089796bde7238f5357b0c23e76)

* Use onMediaMetadataChanged for updating the legacy session

Issue: androidx/media#219
PiperOrigin-RevId: 501080612
(cherry picked from commit 375299bf364041ccef17b81020a13af7db997433)

* Improve Java doc about how to override notification drawables

Issue: androidx/media#140
PiperOrigin-RevId: 501288267
(cherry picked from commit a2cf2221170e333d1d1883e0e86c5efca32f55ba)

* Request notification permission in demo app for API 33+

Starting with API 33 the POST_NOTIFICATION permission needs to be
requested at runtime or the notification is not shown.

Note that with an app with targetSdkVersion < 33
but on a device with API 33 the notification permission is automatically
requested when the app starts for the first time. If the user does not
grant the permission, requesting the permission at runtime result in
an empty array of grant results.

Issue: google/ExoPlayer#10884
PiperOrigin-RevId: 501320632
(cherry picked from commit 6484c14acd4197d335cab0b5f2ab9d3eba8c2b39)

* Document that `DownloadService` needs notification permissions

Starting with Android 13 (API 33) an app needs to request the
permission to post notifications or notifications are suppressed.
This change documents this in the class level JavaDoc of the
`DownloadService`.

Issue: google/ExoPlayer#10884
PiperOrigin-RevId: 501346908
(cherry picked from commit 20aa5bd9263f594e4f1f8029c5b80e9f204bff3a)

* Add AdsLoader.focusSkipButton()

This method allows to call through to `StreamManager.focus()` of the currently playing SSAI stream.

PiperOrigin-RevId: 501399144
(cherry picked from commit 16285ca5dfd4461334f5e97d4de47ae07e49e883)

* Catch FgSStartNotAllowedException when playback resumes

This fix applies to Android 12 and above.

In this fix, the `MediaSessionService` will try to start in the foreground before the session playback resumes, if ForegroundServiceStartNotAllowedException is thrown, then the app can handle the exception with their customized implementation of MediaSessionService.Listener.onForegroundServiceStartNotAllowedException. If no exception thrown, the a media notification corresponding to paused state will be sent as the consequence of successfully starting in the foreground. And when the player actually resumes, another media notification corresponding to playing state will be sent.

PiperOrigin-RevId: 501803930
(cherry picked from commit 0d0cd786264aa82bf9301d4bcde6e5c78e332340)

* Correctly map deprecated methods in MediaController to replacement

This avoids throwing exceptions for correct (but deprecated) Player
method invocations.

PiperOrigin-RevId: 502341428
(cherry picked from commit 86a95c2a4afd861986376f9dc31e0d65910e6e74)

* Remove unneccesary parameter taking Player.Command

The method to dispatch actions in MediaControllerImplBase takes
a Player.Command, but the value is only used to check if we
are setting a surface and need to handle the special blocking
call. This can be cleaned up by removing the parameter and calling
a dedicated blocking method where needed. This also ensures we
have to mention the relevant Player.Command only once in each
method.

PiperOrigin-RevId: 502341862
(cherry picked from commit 664ab72d090196625b5f533e9f0a2112951c5741)

* Add missing command checks to MediaSessionLegacyStub and PlayerWrapper

This player didn't fully check all player commands before calling the
respective methods.

PiperOrigin-RevId: 502353704
(cherry picked from commit a2a44cdc02abadd473e26e1fd9f973210d4c5f0e)

* Fix command check in MediaControllerImplBase

The command check for setDeviceMuted was wrong.

PiperOrigin-RevId: 502355332
(cherry picked from commit cfcce9aec9d92a7067f07b2d9c00d705df0368ac)

* Clarify what default settings are being used for SSAI AdsLoader

PiperOrigin-RevId: 502388865
(cherry picked from commit abe11c88ecdfe56ca31d3bffe1dd8fce6fb293af)

* Post notification for session app when FgS starting exception is caught

PiperOrigin-RevId: 502407886
(cherry picked from commit 6ce3421ca750109acfea35029260dc3f169a1a40)

* Filter what PlaybackStateCompat actions are advertised

PlayerWrapper advertises PlaybackStateCompat actions to the legacy
MediaSession based on the player's available commands.

PiperOrigin-RevId: 502559162
(cherry picked from commit 39f4a17ad4ac3863af22e12711247c7a87b8613e)

* Disables play/pause button when there's nothing to play

PiperOrigin-RevId: 502571320
(cherry picked from commit d49a16e094d6d4bde0d1dc1ec42876c156b9c55a)

* Make availableCommands known when bundling PlayerInfo

When bundling PlayerInfo, we remove data when the controller is not
allowed to access this data via getters. We also remove data for
performance reasons. In the toBundle() method, it's currently hard to
make the connection between allowed commands and filtering, because
the values are checked at a different place. This can be made more
readable by forwarding the applicable Commands directly.

The only functional fix is to filter the Timeline when sending the
first PlayerInfo after a connecting a controller if the command to
get the Timeline is not available. This also allows us to remove a
path to filter MediaItems from Timelines as it isn't used.

PiperOrigin-RevId: 502607391
(cherry picked from commit c90ca7ba5fb9e83956e9494a584ae6b0620e3b14)

* Fix javadoc references to `writeSampleData`

PiperOrigin-RevId: 502821506
(cherry picked from commit 6c14ffc1ecd13393930b9f5ee7ad7a52391d0f65)

* Correctly filter PlayerInfo by available getter commands.

When bundling PlayerInfo, we need to remove information if the
controller is not allowed to access it. This was only partially
done at the moment.

PiperOrigin-RevId: 502852798
(cherry picked from commit 69cfba7c53b563577390e4074fd270f078bf6069)

* Extend command GET_CURRENT_MEDIA_ITEM to more methods.

We currently only document it for the getCurrentMediaItem(), but
the command was always meant to cover all information about the
current media item and the position therein.

To correctly hide information for controllers, we need to filter
the Timeline when bundling the PlayerInfo class if only this
command is available.

PiperOrigin-RevId: 503098124
(cherry picked from commit f15b7525436b45694b5e1971dac922adff48b5ae)

* Update media controller position before pausing.

We stop estimating new position when pausing until we
receive a new position from the player. However, this
means that we will continue to return a possible stale
previous position. Updating the current position before
pausing solves this issue.

PiperOrigin-RevId: 503153982
(cherry picked from commit e961c1b5e9bb4a6f63458b1bdcb49e97f415fabf)

* Add command check for metadata in DefaultMediaNotificationProvider

PiperOrigin-RevId: 503172986
(cherry picked from commit 052c4b3c1a6b72efd7fcbf433c646fed9ea91748)

* Explicitly document most Player.Listener methods in terms of  getters

This makes it implicitly clear that if the value of a getter changes due
to a change in command availability then the listener will be invoked,
without needing to explicitly document every command on every listener
method.

#minor-release

PiperOrigin-RevId: 503178383
(cherry picked from commit 280889bc4a5b7ddc1b1c9fe15e222cad7f2e548a)

* Add the MediaSession as an argument to `getMediaButtons()`

Issue: androidx/media#216
#minor-release
PiperOrigin-RevId: 503406474
(cherry picked from commit e690802e9ecf96dfbb972864819a45ae92c47c90)

* Add onSetMediaItems listener with access to start index and position

Added onSetMediaItems callback listener to allow the session to modify/set MediaItem list, starting index and position before call to Player.setMediaItem(s).

Added conditional check in MediaSessionStub.setMediaItem methods to only call player.setMediaItem rather than setMediaItems if player does not support COMMAND_CHANGE_MEDIA_ITEMS

PiperOrigin-RevId: 503427927
(cherry picked from commit bb11e0286eaa49b4178dfa29ebaea5dafba8fc39)

* Add missing # in release notes

PiperOrigin-RevId: 504013985
(cherry picked from commit 5147011772286778e84410012a24e329fde12040)

* Deduplicate onSetMediaItem handler logic

Created unified MediaUtils method to handle various logic for calling Player.setMediaItems from MediaSessionStub and MediaSessionLegacyStub

PiperOrigin-RevId: 504271877
(cherry picked from commit 7fbdbeb6cafe075f04b6a4321ef826643b3482e1)

* Suppress warnings in ImaUtil

ImaUtil calls VideoProgressUpdate.equals() which is annotated as hidden,
which causes lint errors with gradle.

#minor-release

PiperOrigin-RevId: 504306210
(cherry picked from commit 5f6e172c8fce652adf2c05e8f2d041c793e900ea)

* Filter available commands based on PlaybackStateCompat actions

This allows a MediaController to understand which methods calls
are available on a legacy session.

PiperOrigin-RevId: 504306806
(cherry picked from commit 067340cb0a03dede0f51425de00643fe3789baf2)

* Publish gradle attributes for AndroidX compatibility

These attributes are required when importing our artifacts into
androidx-main in order to generate reference documentation (JavaDoc and
KDoc).

#minor-release

PiperOrigin-RevId: 504502555
(cherry picked from commit 47349b8c4bd69415da8895061be71ef748c4a2d3)

* Add missing } to publish.gradle

This was missed in https://github.com/androidx/media/commit/47349b8c4bd69415da8895061be71ef748c4a2d3

#minor-release

PiperOrigin-RevId: 504548659
(cherry picked from commit 50beec56f4188e46f67e561ac4bb4ace5bb95089)

* Add missing command checks in UI module

The commands are partly checked already before enabling
features or calling player methods, but the checks were
still missing in many places.

#minor-release

PiperOrigin-RevId: 504589888
(cherry picked from commit e2ece2f5bcda0cea436d782d58fa6f1d9a4d1f99)

* Tweak UI behavior when commands are missing.

For most missing commands, we already disable the corresponding
controls. This change extends this to more UI elements that are
disabled in case the corresponding action is unavailable.

#minor-release

PiperOrigin-RevId: 505057751
(cherry picked from commit b3e7696ba7d66a2d3c477858194a20789f4d75c7)

* Match MergingMediaPeriod track selection by period index in id

MergingMediaPeriod creates its track groups with ids concatenating position in its periods array and the underlying child track group id. The ids can be used in selectTracks for matching to periods list.

Issue: google/ExoPlayer#10930
PiperOrigin-RevId: 505074653
(cherry picked from commit 542a1ef03f361b29ec731a7334b2922cb54ef4c9)

* Double tap detection for Bluetooth media button events only

Issue: androidx/media#233
#minor-release
PiperOrigin-RevId: 505078751
(cherry picked from commit 5c82d6bc18429842160bb64a851bb1ab5c89ec39)

* Fix timestamp comparison for seeks in fMP4

When seeking in fMP4, we try to extract as little samples as possible
by only starting at the preceding sync frame. This comparison should
use <= to allow sync frames at exactly the seek position.

Issue: google/ExoPlayer#10941

PiperOrigin-RevId: 505098172
(cherry picked from commit 00436a04a4f0fec8ee9154fc1568ca4013ca5c7d)

* Inline method in PlayerService that is used from on call site only

#cleanup
#minor-release

PiperOrigin-RevId: 505146915
(cherry picked from commit d7ef1ab5bd5a4508c0913011f5990bb03a57585a)

* Do not assume a valid queue in 3rd party sessions

This change fixes an issue that can be reproduced when
a controller `onConnect` creates a `QueueTimeline` out
of the state of a legacy session and then `prepare` is called.

`activeQueueItemId`, `metadata` and the `queue` of the legacy
session are used when a `QueueTimeline` is created. The change
adds unit tests to cover the different combinatoric cases these
properties being set or unset.

PiperOrigin-RevId: 505731288
(cherry picked from commit 4a9cf7d069b1b35be807886d59d87c396b19876c)

* Fix (another) `LeanbackPlayerAdapter` param name mismatch

I missed this when fixing `positionInMs` for Dackka in https://github.com/androidx/media/commit/aae6941981dfcfcdd46544f585335ff26d8f81e9

This time I manually verified that all the `@Override` methods have
parameter names that match [the docs](https://developer.android.com/reference/androidx/leanback/media/PlayerAdapter).

#minor-release

PiperOrigin-RevId: 506017063
(cherry picked from commit d1a27bf2a81709bc7b03ad130bc9abd4d8b27164)

* Merge pull request #10793 from fraunhoferfokus:dash-thumbnail-support

PiperOrigin-RevId: 506261584
(cherry picked from commit c6569a36fbce6fc3ece55c9a904508bd4a4c45da)

* Publish ConcatenatingMediaSource2

Can be used to combine multiple media items into a single timeline window.

Issue: androidx/media#247
Issue: google/ExoPlayer#4868
PiperOrigin-RevId: 506283307
(cherry picked from commit fcd3af6431cfcd79a3ee3cc4fee38e8db3c0554e)

* Session: advertise legacy FLAG_HANDLES_QUEUE_COMMANDS

This change includes 3 things:
- when the legacy media session is created, FLAG_HANDLES_QUEUE_COMMANDS
  is advertised if the player has the COMMAND_CHANGE_MEDIA_ITEMS
  available.
- when the player changes its available commands, a new
  PlaybackStateCompat is sent to the remote media controller to
  advertise the updated PlyabackStateCompat actions.
- when the player changes its available commands, the legacy media
  session flags are sent accoridingly: FLAG_HANDLES_QUEUE_COMMANDS is
  set only if the COMMAND_CHANGE_MEDIA_ITEMS is available.

#minor-release

PiperOrigin-RevId: 506605905
(cherry picked from commit ebe7ece1eb7e2106bc9fff02db2666410d3e0aa8)

* Fix release note entry

* Prepare media3 release notes for rc01

PiperOrigin-RevId: 509218510
(cherry picked from commit 73909222706c6d7a56e0fb2d09ed8b49eca5b2be)

* Minor fixes in release notes

PiperOrigin-RevId: 509222489
(cherry picked from commit a90728fdc66cc2a8929cce9d67081681e0168115)

* Version bump for ExoPlayer 2.18.3 & media3-1.0.0-rc01

#minor-release

PiperOrigin-RevId: 509501665
(cherry picked from commit 20eae0e041e1922fd79ca36218054b293a9da7da)

* Detect HEVC HDR10 codec profile more accurately

In MediaCodecUtil, use Format.colorInfo, besides the codec string,
to accurately map to a 10bit HEVC profile.

PiperOrigin-RevId: 507500071
(cherry picked from commit a50ea94525d2522436fbc812dec12aee53b3c1bf)

* Fix AudioTrackPositionTracker logic for playback speed adjustments

The AudioTrackPositionTracker needs to correct positions by
the speed set on the AudioTrack itself whenever it makes
estimations based on real-time (=the real-time playout
duration is not equal to the media duration played).

This happens for the main playback path already, but not for
the mode in which the position is estimated from the playback
head position and also not in the phase after the track has
been stopped. Both cases are not very noticeable during
normal playback, but become relevant when playing in offload
mode.

PiperOrigin-RevId: 507736408
(cherry picked from commit 01d7bc72794b98d19cad2be5c70de2f755bff9f1)

* Merge pull request #248 from lemondoglol:update-segment-size

PiperOrigin-RevId: 507784608
(cherry picked from commit ecd91d865c0888c6cc1aa3554877f4df798f5379)

* Merge pull request #10959 from balachandarlinks:handle-sql-exception-in-cached-content-index

PiperOrigin-RevId: 508323432
(cherry picked from commit 1249dcdc47a4c3b4dbd642c3991945b23de8112b)

* Document spatialization behavior constants.

PiperOrigin-RevId: 508602059
(cherry picked from commit 6066ce43f66317f708e6e0076580e1bc1182186d)

* Add null check to `ExoPlayerImpl.isTunnelingEnabled`

`TrackSelectorResult.rendererConfigurations` can contain null elements:
> A null entry indicates the corresponding renderer should be disabled.

This wasn't caught by the nullness checker because `ExoPlayerImpl` is
currently excluded from analysis.

#minor-release

Issue: google/ExoPlayer#10977
PiperOrigin-RevId: 508619169
(cherry picked from commit a6dfcf779942cb76c495fb5f7bc5444da6147b9d)

* AsynchronousMediaCodecAdapter: surface queueing errors sooner

The AsynchronousMediaCodecAdapter's queuing thread stores any exceptions
raised by MediaCodec and re-throws them on the next call to
queueInputBuffer()/queueSecureInputBuffer(). However, if MediaCodec
raises and error while queueing, it goes into a failed state and does
not announce available input buffers. If there is no input available
input buffer, the MediaCodecRenderer will never call
queueInputBuffer()/queueSecureInputBuffer(), hence playback is stalled.

This change surfaces the queueing error through the adapter's dequeueing
methods.

PiperOrigin-RevId: 508637346
(cherry picked from commit 706431059cadf1b503ea8f95fd482d41f48e1a1c)

* Add ad event listeners in the Looper event of the ad manager callback

#minor-release

PiperOrigin-RevId: 509189206
(cherry picked from commit 51929625cfeff17af413c1a06c87e10e72f218d1)

* Catch IllegalArgumentExceptions in RTSP Response parsing

In parsing Describe RTSP response messages, IllegalArgumentExceptions are thrown for invalid parameters and values. These exceptions were not caught and crashed the Playback thread. Now these exceptions will be caught and their errors forwarded to the proper error handling listeners.

Issue: google/ExoPlayer#10971
PiperOrigin-RevId: 509207881
(cherry picked from commit a8c87453db02658a21293b44b017a70d5ae1125d)

* Add exception cause to thrown exception

PiperOrigin-RevId: 509473556
(cherry picked from commit 56803bf1ad3e4df2ebd8d7b38f5a9f4740dc702f)

* Fix error in documentation string

The current javadoc refers to the SessionCallback#onConnected, which doesn't exist.

PiperOrigin-RevId: 510261965
(cherry picked from commit fc642eb45f6c997a2a501bcc3ea19043cd9911eb)

* Map `PLAYER_STATE_LOADING` to `STATE_BUFFERING`

#minor-release
Issue: androidx/media#245
PiperOrigin-RevId: 510456793
(cherry picked from commit ba49b6b81b9a6a01aa16381cca70886bc205c5c5)

* Reduce number of calls to AudioTrack.getPlaybackHeadPosition

This call may cause performance overhead in some situations,
for example if the AudioTrack needs to query an offload DSP
for the current position. We don't need to check this multiple
times per doSomeWork iteration as the value is unlikely to
change in any meaningful way.

PiperOrigin-RevId: 510957116
(cherry picked from commit 9eccf09165f39d89d502065f897d120b97f47f66)

* Skip rendering multiple frames on the same vsync

When rendering frames at a rate higher than the screen refresh rate,
e.g. playing at 8x, the player is releasing multiple frames at the same
release time (nanos) which are then dropped by the platform. The output
buffers are available later and as a result MediaCodec cannot keep up
decoding fast enough.

This change skips releasing multiple video frames on the same vsync
period and proactivelly drops the frame. The frame is counted as skipped
rather than dropped to differentiate with frames dropped due to slow
decoding.

PiperOrigin-RevId: 510964976
(cherry picked from commit ab7e84fb34b7ef4b13e492e1f8918345c712ec30)

* Use ArrayDeque for pending output stream changes.

The current logic uses manual array operations to keep track of pending
changes. Modernize this code by using an ArrayDeque and a data class.
This also allows to extend the output stream information in the future.

This also fixes a bug where a position reset accidentally assigns a pending
stream offset instead of keeping the current one.

PiperOrigin-RevId: 511787571
(cherry picked from commit f0420124954527e7f3eb529ca24f2a51dc7319f9)

* Do not specify export flags for protected system broadcasts.

Protected system broadcasts should not specify the export flag.
Marking them as NOT_EXPORTED breaks sticky broadcasts in some
cases.

Issue: google/ExoPlayer#10970

PiperOrigin-RevId: 512020154
(cherry picked from commit 93e117928c157ef338faa46dea25ee114f18d3eb)

* Use more realistic time values for MediaCodecVideoRendererTest

This test became flaky after https://github.com/androidx/media/commit/ab7e84fb34b7ef4b13e492e1f8918345c712ec30 because some of the
unrealistic frame times ended up on the same release time.

Using realistic numbers avoids the flakiness.

PiperOrigin-RevId: 512566469
(cherry picked from commit 0c8ce183fe7e2f065ca4dea33818566e9aeff48f)

* Correctly update output info if previous stream has been fully rendered

The output info for a new stream is marked pending until the last
sample of the previous stream has been processed. However, this fails
if the previous stream has already been fully processed. We need to
detect this case explicitly to avoid signalling the output change one
sample too late.

#minor-release

PiperOrigin-RevId: 512572854
(cherry picked from commit 7ffcc6f7ea648fb89b487f4c381b1d886cc8a638)

* Add workaround for wrong PerformancePoints on some devices.

Some devices were reported to have wrong PerformancePoint sets
that cause 60 fps to be marked as unsupported even though they
are supported.

Issue: google/ExoPlayer#10898

PiperOrigin-RevId: 512580395
(cherry picked from commit d0cbf0fce84aa73be5eb68935d6a4dd2f2e1dc3d)

* Ensure output format is updated in sync with stream changes.

MediaCodecRenderer currently has two independent paths to trigger
events at stream changes:
 1. Detection of the last output buffer of the old stream to trigger
    onProcessedStreamChange and setting the new output stream offset.
 2. Detection of the first input buffer of the new stream to trigger
    onOutputFormatChanged.
Both events are identical for most media. However, there are two
problematic cases:
  A. (1) happens after (2). This may happen if the declared media
     duration is shorter than the actual last sample timestamp.
  B. (2) is too late and there are output samples between (1) and (2).
     This can happen if the new media outputs samples with a timestamp
     less than the first input timestamp.

This can be made more robust by:
 - Keeping a separate formatQueue for each stream to avoid case A.
 - Force outputting the first format after a stream change to
   avoid case B.

Issue: google/ExoPlayer#8594

PiperOrigin-RevId: 512586838
(cherry picked from commit 3970343846d7bae5d8ae331d74241c50777ce18a)

* Update notification play/pause button with matching player state

Issue: androidx/media#192
PiperOrigin-RevId: 508649684
(cherry picked from commit e1d12fc395d9f9edb28755a5b1026e26b378e005)

* Fix some playback parameter signalling problems.

Playback parameter signalling can be quite complex because
 (a) the renderer clock often has a delay before it realizes
     that it doesn't support a previously set speed and
 (b) the speed set on media clock sometimes intentionally
     differs from the one surfaced to the user, e.g. during
     live speed adjustment or when overriding ad playback
     speed to 1.0f.

This change fixes two problems related to this signalling:
 1. When resetting the media clock speed at a period transition,
    we don't currently tell the renderers that this happened.
 2. When a delayed speed change update from the media clock is
    pending and the renderer for this media clock is disabled
    before the change can be handled, the pending update becomes
    stale but it still applied later and overrides any other valid
    speed set in the meantime.

Both edge cases are also covered by extended or new player tests.

Issue: google/ExoPlayer#10882

PiperOrigin-RevId: 512658918
(cherry picked from commit e79b47ccff39363543c514937aef517a855994f0)

* Ensure getPlaybackHeadPosition isn't called if not needed

Once the value returned from AudioTimestampPoller advances, we
only need getPlaybackHeadPosition to sample sync params and
verify the returned timestamp. Both of these happen less often
and we can avoid calling getPlaybackHeadPosition if we don't
actually need it.

PiperOrigin-RevId: 512882170
(cherry picked from commit 408b4449ff75e29a9bda7adc1b530b993fc47814)

* Update translations

#minor-release

PiperOrigin-RevId: 512890813
(cherry picked from commit a7faa5bfd8c82e22c7d99378cf78f31a57274db2)

* Minor change in ForwardingPlayer javadoc

#minor-release

PiperOrigin-RevId: 512897269
(cherry picked from commit 42fae152d0ad381c8bbb0858f596770529f11f40)

* Remove @see tags with <a> tags

These are not supported by Dackka

#minor-release

PiperOrigin-RevId: 513176533
(cherry picked from commit c07cf3dc414b562652cdd4f3b0e91f80493a2c40)

* Merge pull request #255 from mayurk2:use_edts_offset_if_it_is_for_entire_file

PiperOrigin-RevId: 513213229
(cherry picked from commit 17499cefcc1b27d90ecdf136bd3b2e4856ddcaf1)

* Update release notes for 1.0.0-rc02

PiperOrigin-RevId: 513483809
(cherry picked from commit df11545ba18f9bf3e6e9c87c3bdb30bfb0723279)

* Bump version numbers to Media3 1.0.0-rc02 and ExoPlayer 2.18.4

#minor-release

PiperOrigin-RevId: 513488487
(cherry picked from commit cd753bd7b8c3206b509949e851f515ca465e4c89)

* Fix some JavaDoc in the Media3 session module

#minor-release

PiperOrigin-RevId: 513501046
(cherry picked from commit 6042bec18a4b30449a20d1e858bac799cc6d18c3)

* Remove unreleased changed

* Fix lint-baseline.xml for latest UI translations

#minor-release

PiperOrigin-RevId: 513533248
(cherry picked from commit 8498e4b4445ae88665c6cdbc4e47e8e6ca7b7303)

* Add missing RELEASENOTES line

PiperOrigin-RevId: 513556883
(cherry picked from commit e2cb32f34ce016877fa7d2f4acc38511e7c261c0)

* Shorten labels to fix transformer demo UI

* Shorten labels to fix transformer demo UI

* Add missing `@param` tags

Dackka generates a warning if a method has at least one `@param` tag,
but not all of them are documented.

PiperOrigin-RevId: 513873453
(cherry picked from commit cb7d565fd47fc0b818ec0d5c7529e19df44022b5)

* Update templates to more clearly signpost between exoplayer2 and media3

Issue: google/ExoPlayer#11031

#minor-release

PiperOrigin-RevId: 514366016
(cherry picked from commit 9c82923094400e0b840a983e55be26b1dd76e7d2)

*…
@imansdn
Copy link

imansdn commented Aug 1, 2023

Hi do we have any update for this?
I've been facing same challenges with Media3 recently, and I could really use some help. To give you a brief overview, I migrated our app from ExoPlayer to Media3 and followed Google's migration guide. However, it appears that there's no straightforward way to handle MediaButton KeyEvent actions manually.
I've been trying to find a solution, but so far, I haven't been successful.
I tried to elaborate my question in in this post

I'd greatly appreciate any insights or suggestions you may have on how to handle MediaButton actions manually with Media3.

Thanks

@marcbaechinger
Copy link
Contributor

I'm not quite sure how your question is related to this issue. I think #249 may be more interesting for you.

It appears that there's no straightforward way to handle MediaButton KeyEvent actions manually.

That's true. I think you shouldn't focus on media button events, but instead solve your problem with the Media3 API. Besides Bluetooth, media button events are only a thing for actions coming from the notification below API 33. I wouldn't recommend going on this rather lower-level API because on API 33 and above the notification sends commands directly to the session without using media button events.

MediaButton events coming from a Bluetooth device are delivered by the system to the platform media session that delegates them to onMediaButtonEvent of the MediaSession.Callback and then delegates to MediaSessionCompat.Callback.onSkipToNext(). That's where Media3 receives it after the media button event has been resolved by the platform session to the specific callback method onSkipToNext:

onSkipToNext:455, MediaSessionLegacyStub (androidx.media3.session)
onSkipToNext:1691, MediaSessionCompat$Callback$MediaSessionCallbackApi21 (android.support.v4.media.session)
onMediaButtonEvent:967, MediaSession$Callback (android.media.session)
onMediaButtonEvent:1611, MediaSessionCompat$Callback$MediaSessionCallbackApi21 (android.support.v4.media.session)
handleMessage:1593, MediaSession$CallbackMessageHandler (android.media.session)
dispatchMessage:106, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7884, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:936, ZygoteInit (com.android.internal.os)

Media3 then delegates the event to the player.

I'm not quite sure why you are trying to intercept media button events from your question. I assume you want to intercept commands coming from a BT headset.

If I'm right, then you can try to wrap the player in a ForwardingPlayer before you pass it to the Builder with which you build your session. This is an approach where you don't have to care about API levels or similar:

val forwardingPlayer =
  object : ForwardingPlayer(player) {

    override fun seekToPrevious() {
      val packageName = mediaLibrarySession.controllerForCurrentRequest?.packageName
      if (packageName == "com.google.android.bluetooth") {
        previousSegment()
        return;
      }
      super.seekToPrevious()
    }

    override fun seekToNext() {
      val packageName = mediaLibrarySession.controllerForCurrentRequest?.packageName
      if (packageName == "com.google.android.bluetooth") {
        nextSegment()
        return;
      }
      super.seekToNext()
    }
  }

mediaLibrarySession =
  MediaLibrarySession.Builder(this, forwardingPlayer, librarySessionCallback)
    .build()

session.controllerForCurrentRequest is the controller that sent the command and you can filter this way to only change the behavior for Bluetooth. If you want to change this behavior generally, you obviously don't need this check.

Can you try if this is an approach that would work for you?

@Shabinder
Copy link

I only play one media item at a time, however I need to show skip to next / skip to prev button and handle them manually.
Could use a forwarding player to intercept the command but I couldnt find a way to show skip to next and prev buttons without building a playlist in exoplayer.

Any advice on this ?

@marcbaechinger
Copy link
Contributor

Have you tried overriding getAvailableCommands() and isCommandAvailable(int command) with your ForwardingPlayer and then make sure COMMAND_SEEK_TO_NEXT and COMMAND_SEEK_TO_PREVIOUS is always available? If the command is available, the button is drawn by the notification.

@Shabinder
Copy link

Forgot to update it here, but earlier I tried this and shipped the new release of my app with above change only.
Thanks @marcbaechinger .

@ygormsantos
Copy link

I was able to hide the buttons I didn't want overriding getAvailableCommands. Now I'm implementing seek for the current MediaItem.

Is there a way to enable this command without adding it to the notification?

@panzhiev
Copy link

panzhiev commented Sep 1, 2023

@marcbaechinger Hi! I ran into a problem with my app intercepting media actions from the mini player (media notification) and headphones. The problem is that ExoPlayer and its setup is on the side of the sdk I'm using (so I can't use ForwardingPlayer for this purpose), while the MediaSessionService is on the client side. Each time, before the user presses the PLAY button, I need to check some conditions on the client - and only then pass (or not pass) this event to the player. In the case of the mini player, I did not find a way to intercept pressing the PLAY / PAUSE button in the notification. I tried to do it via onStartCommand of my service by KeyCode but it looks like a hack. Perhaps there is a more elegant way to intercept this event?

@marcbaechinger
Copy link
Contributor

I think the best would be if the SDK provides you some API for this. If an SDK is burrying the API provided by a library that they wrap then I think the SDK should be in charge to either provide a way to integrate differently or expose the existing API to not restrict their users.

So the ForwardingPlayer is indeed what you should be able to do. Because the notification sends playback commands via PendingIntent or directly to the session depending on the API level. Overriding onStartCommand only gives you the commands below API 33. You also don't receive media button events on API 26 and later that for instance are coming from a Bluetooth events. The system sends these directly to the session as well. All of these eventuality arrive at the ForwardingPlayer. That's why this is the solution.

user presses the PLAY button, I need to check some conditions on the client - and only then pass (or not pass) this event to the player.

I don't think this is a good idea, because in the case of PLAY commands, the service is expected to be put in the foreground. Media3 puts the service in the foreground when the player is playing. So if you intercept the wrong Play event, then your app may crash with a ForegroundServiceDidNotStartInTimeException on API 31 and higher. See #167 for more details.

I'm not sure about your use case, but regarding Play commands, it's better to make sure that a given sender does not have an option to send the play command (like not showing a Play button). Once the command is sent, it's probably too late because it's risky to stop a Play command and turn it into a no-op for the reasons given above.

@phcannesson
Copy link

If I may add, one very common use-case where I would want to detect clicks on the notification is analytics.
Knowing if a next action comes from the app, the media controls or elsewhere.

@marcbaechinger
Copy link
Contributor

@phcannesson

If I may add, one very common use-case where I would want to detect clicks on the notification is analytics.

In the main branch we added a method MediaSession.isMediaNotificationController(controllerInfo). Starting with the next release 1.2.0, an app can recognize whether a player command or a custom command is coming from the notification with this method:

val forwardingPlayer = object: ForwardingPlayer(player) {
      override fun play() {
        val controller = mediaLibrarySession.controllerForCurrentRequest
        controller?.let {
          if (mediaLibrarySession.isMediaNotificationController(controller)) {
            // handle command coming from media notification
          } 
        }
        super.play()
      }
    }

This sounds like would be useful for your use case of analytics. Media3 makes sure that the calling controller is always the same on all API levels. Under the hood, the commands can come from a PendingIntent or sent directly to the session starting with API 33. However, Media3 makes sure it always has the same calling controller that you can recognize with this helper method conveniently.

copybara-service bot pushed a commit that referenced this issue Oct 20, 2023
This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: #12
Issue: #159
Issue: #216
Issue: #249

#minor-release

PiperOrigin-RevId: 575231251
rohitjoins pushed a commit that referenced this issue Oct 23, 2023
This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: #12
Issue: #159
Issue: #216
Issue: #249

#minor-release

PiperOrigin-RevId: 575231251
(cherry picked from commit a79d44e)
rohitjoins pushed a commit that referenced this issue Oct 24, 2023
This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: #12
Issue: #159
Issue: #216
Issue: #249

#minor-release

PiperOrigin-RevId: 575231251
(cherry picked from commit a79d44e)
@k-arabadzhiev
Copy link

I had to customize the SEEK_TO_PREVIOUS/SEEK_TO_NEXT icons for notification player and looking at this issue (and some others) I've come to a conclusion that I need to add custom session commands AND also remove the player commands (COMMAND_SEEK_TO_PREVIOUS, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) so they don't show in the notification.

In my case I have to have different buttons in the notification depending on the type of media that is currently playing (i.e. live media shouldn't have seek forward or back, only play/pause)

So I though the best place for me to change the commands is in MediaLibrarySession.Callback.onGetItem (I'm open to criticism, if this is not correct):

override fun onGetItem(
    session: MediaLibrarySession,
    browser: MediaSession.ControllerInfo,
    mediaId: String
): ListenableFuture<LibraryResult<MediaItem>> {
    // for versions below Android 13 I have CustomMediaNotificationProvider, 
    // extending DefaultMediaNotificationProvider with overriden getMediaButtons method
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (mediaItem.isLive) {
            session.mediaNotificationControllerInfo?.let {
                session.setAvailableCommands(
                    it,
                    MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS,
                    MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS
                )
            }
        } else {
            val availableSessionCommands =
                MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
            notificationPlayerCustomCommandButtons.forEach { commandButton ->
                commandButton.sessionCommand?.let { availableSessionCommands.add(it) }
            }
            val playerCommands =
                MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
                    .removeAll(
                        COMMAND_SEEK_TO_PREVIOUS,
                        COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM,
                        COMMAND_SEEK_TO_NEXT,
                        COMMAND_SEEK_TO_NEXT_MEDIA_ITEM,
                    ).build()
            session.mediaNotificationControllerInfo?.let {
                session.setAvailableCommands(
                    it,
                    availableSessionCommands.build(),
                    playerCommands
                )
            }
        }
    }
    LibraryResult.ofItem(
        mediaItem,
        LibraryParams.Builder().build()
    )
}

And then in onCustomCommand I can make everything work as expected:

override fun onCustomCommand(
    session: MediaSession,
    controller: MediaSession.ControllerInfo,
    customCommand: SessionCommand,
    args: Bundle
): ListenableFuture<SessionResult> {
    if (customCommand.customAction == NotificationPlayerCustomCommand.PREVIOUS.customAction) {
        session.player.seekToPrevious()
    }
    // other custom commands
    return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}

However, what I don't understand and I find really counterintuitive is why does this even work? To be more specific, why is this line working:

session.player.seekToPrevious()

if the underlying player command has been removed? Even the documentation for seekToPrevious mentions:

This method must only be called if COMMAND_SEEK_TO_PREVIOUS is available.

@marcbaechinger
Copy link
Contributor

marcbaechinger commented Jan 5, 2024

me to change the commands is in MediaLibrarySession.Callback.onGetItem

onGetItem being called is not related to what is currently in the player. It probably works for your specific app in case you are using this method before setting the item to the player, but from the library side there is not relationship between onGetItem and what is playing.

I would recommend listening to Player.Listener.onMediaItemTransitioned instead. That is the event that is emitted by the player when the item currently being played changed. That's when you want to customize the notification for that item I think and independent from how this media item is set into the player. You want to listen to the result, not the action that triggers this result.

if the underlying player command has been removed? Even the documentation for seekToPrevious mentions:

Your code removes the commands from a specific controller, not from the player. While the controller can't send the command and the session would drop it if it arrives, the player can still do everything if an app wants it.

This only removes the command from the controller. I think this is correct and works as intended:

session.mediaNotificationControllerInfo?.let {
    session.setAvailableCommands(
        it,
        availableSessionCommands.build(),
        playerCommands
    )
}

It's a common scenario that you may want to have different commands available for different controllers. You only remove this from the controller, so that that specific controller can't send such a command. However, under the hood you as the app should still be able to call every command on the actual player. Else removing a command on controller A would disallow calling such a method for all controller, which is not intended.

@k-arabadzhiev
Copy link

I would recommend listening to Player.Listener.onMediaItemTransitioned instead

Thanks! I'll check how to do it using this method.

Your code removes the commands from a specific controller, not from the player

Oh yeah right I'm only changing the notification controller, my bad. Really silly to not notice that's how it works, when it's kinda obvious now. Thanks!

It's a common scenario that you may want to have different commands available for different controllers.

Indeed, that's what I'm doing right now actually and I think it finally clicked after reading your comment.

@marcbaechinger
Copy link
Contributor

Ok, cool. Thanks for confirming.

I'm actually going to close this issue. Mostly because it has diverged a bit from the initial report that looks answered. The conversations here are not easily to find under this broad umbrella bug. :)

Don't hesitate to open a new issue with a more specific subject, if you have further questions. Happy to help!

guoen21 added a commit to DiceTechnology/androidx-media that referenced this issue Feb 20, 2024
* Remove some debugging lines in `AtomParsers`

These were accidentally added in https://github.com/androidx/media/commit/885ddb167e3ac164e2ee6dfcf3886c703a45bc38

PiperOrigin-RevId: 565035337

* Compositor: Move input source javadoc to class-level.

As discussed offline, this is important for users of the class, and not all users may choose to read method javadoc, so best to make sure it's visible by leaving it at the class-level.

PiperOrigin-RevId: 565057677

* Change SubtitleParser interface to support incremental output

This change introduces two new types of method to `SubtitleParser`:
1. `parse()` methods that take a `Consumer<CuesWithTiming>` and return `void`
2. `parseToLegacySubtitle` method that returns `Subtitle`

(1) ensures that in the new 'parse before SampleQueue' world we can
write cues to the `SampleQueue` as soon as they're ready - this is
especially important when parsing monolithic text files, e.g. for a
whole movie.

(2) ensures that during the transition, the legacy 'parse after
SampleQueue' behaviour doesn't see any regressions in 'time to first
cue being shown'. Previously we had a single implementation to convert
from `List<CuesWithTiming>` to `Subtitle`, but this relies on the
complete list of cues being available, which can take a long time for
large files in some formats (with ExoPlayer's current parsing logic).
By allowing implementations to customise the way they create a
`Subtitle`, we can directly re-use the existing logic, so that the
'time to first cue being shown' should stay the same.

This change migrates all **usages** to the new methods, but doesn't
migrate any **implementations**. I will migrate the implementations in
follow-up CLs before deleting the old list-returning `parse()` methods.

PiperOrigin-RevId: 565057945

* Add overflow tests for sample count to duration conversion methods

These methods were updated to use the new overflow-resistant
`scaleLargeValue` method in https://github.com/androidx/media/commit/885ddb167e3ac164e2ee6dfcf3886c703a45bc38.

PiperOrigin-RevId: 565059609

* Add javadoc to `SubtitleParser.OutputOptions`

PiperOrigin-RevId: 565066243

* Rollback of https://github.com/androidx/media/commit/e2882c051b35c8b3f71fb63992680c84ae048668

PiperOrigin-RevId: 565069442

* Add test for MultiInputVideoGraph

This test composites the first frame from two video inputs.

PiperOrigin-RevId: 565090338

* Move listener methods into private method for readability

The logic that handles components' boundaries are grouped together in private
methods, like handling VideoCompositor's output textures.

PiperOrigin-RevId: 565131579

* Move bitmap loader tests in test

These tests were under androidTest because we needed a functional
BitmapFactory. Robolectric now supports decoding bitmaps so moving them
under tests.

PiperOrigin-RevId: 565181239

* Compositor: Document VideoCompositor interface thread safety.

PiperOrigin-RevId: 565388982

* Return TIME_UNSET for last sync sample if there is no video track

PiperOrigin-RevId: 565395263

* Upgrade Guava dependency to 32.1.2

Android's version of Guava was upgraded in http://r.android.com/2731599

PiperOrigin-RevId: 565396612

* Read muxedPartialVideo only in MUXER_MODE_MUX_PARTIAL_VIDEO mode

When we switch from MUXER_MODE_MUX_PARTIAL_VIDEO to MUXER_MODE_APPEND_VIDEO
`muxedPartialVideo` will already be `true` so `endTrack` method will pass
through this `if(muxedPartialVideo)` check which is incorrect.

PiperOrigin-RevId: 565398117

* Compositor: Move Settings to DefaultVideoCompositor.

This previously was in the VideoCompositor class, but wasn't
referenced at all from that interface.

PiperOrigin-RevId: 565409646

* Support multiple streams in the ImageRenderer

PiperOrigin-RevId: 565410924

* Compositor: Split out OpenGL drawing logic into inner class.

Organize logic a bit by splitting logic about how we draw using OpenGL onto a
texture, out from the larger class, which has lots of logic discussing how we select
frames and streams.

No functional change intended, but a few method calls are shuffled around to
simplify things.

PiperOrigin-RevId: 565426225

* Fix flaky test becasue ExtTexMgr is not using emulator settings

When running on emulators, ExternalTextureManager needs a longer timeout for
forcing EOS, but we didn't catch a device name running on blaze: `generic_x86`

PiperOrigin-RevId: 565513152

* Open progress conditionVariable when quitting internal thread.

If getProgress is blocking whilst the internal thread calls endInternal
(for error or success), the condition is never opened. Related to this,
onCompleted and onError are therefore never surfaced to the app.

progressState is accessed from application and internal threads, so
should be marked volatile to prevent a thread caching the value.

PiperOrigin-RevId: 565720184

* Change UI module documentation link

PiperOrigin-RevId: 566257915

* Rollback of https://github.com/androidx/media/commit/d58f5fdf7d9421850d4059dda4d3777f5fe03b85

PiperOrigin-RevId: 566258299

* Add QuickTime (Classic) support to `Mp4Extractor`

PiperOrigin-RevId: 566272132

* Compositor: Remove obsolete TODO

PiperOrigin-RevId: 566327798

* Fix ErrorProne lint actionable items

PiperOrigin-RevId: 566571653

* Decouple output size listener and setting output surface

This is because `onOutputSizeChanged()` should in theory be called on the
listener executor.

PiperOrigin-RevId: 566591784

* Update `WebvttParser` to implement new partial-output method

This requires adapting the 'to `CuesWithTiming` list' logic to work with
the new partial-output API, and that needs a private method so it's no
longer a good fit for a default method on `Subtitle` - hence moving it
to a new utility class.

Also update the implementation to never return `UNSET` duration (this is
an equivalent change to the `SsaParser` change in https://github.com/androidx/media/commit/9631923440b8be2239225a2099842410548c7ebd).

PiperOrigin-RevId: 566598094

* Switch `WebvttParserTest` to use partial-output method

PiperOrigin-RevId: 566598735

* Move setAudioAttributes from ExoPlayer to Player

PiperOrigin-RevId: 566607528

* Add two helpful methods to FakeMediaSource for testing

PiperOrigin-RevId: 566636545

* Update `external/guava/METADATA` link from `master` to `main` branch

PiperOrigin-RevId: 566645434

* Remove using Consumer of ExportException in VideoGraphs

PiperOrigin-RevId: 566651267

* Don't call `MediaSession.Callback.onPostConnect` if connecting failed

I spotted that this looked wrong while investigating test various
session test failures. However, changing this logic doesn't seem to
affect the tests so I don't know if the change is an improvement or not.

PiperOrigin-RevId: 566655318

* Re-land: `TtmlParser` implementation - moved from `TtmlDecoder`

This change uses the new incremental overloads of `SubtitleParser` to
avoid introducing the performance regression caused by the original
change requiring all cues to be fully parsed before the first could be
shown on screen.

`TtmlDecoder` which used to be `SimpleSubtitleDecoder` will now be
called `TtmlParser` and implement `SubtitleParser` interface. For
backwards compatibility, we will have the same functionality provided
by `DelegatingSubtitleDecoder` backed-up by a new `TtmlParser`
instance.

PiperOrigin-RevId: 566671398

* Deprecate `Util.getAudioContentTypeForStreamType`

This method isn't used by the library (since <unknown commit>).

It doesn't really work well (e.g. arbitrarily defaults to `MUSIC` when
`UNKNOWN` would be a better default). There's no suggested replacement.

PiperOrigin-RevId: 566676744

* Use a longer timeout for running Transformer on emulators

PiperOrigin-RevId: 566688502

* Create `AudioOffloadPreferences` class

Move audio offload mode related interfaces and definitions from `TrackSelectionParameters` to a new `AudioOffloadModePreferences` class.

PiperOrigin-RevId: 566905017

* TTML: Remove unused `CellResolution.columns` and collapse to `int rows`

PiperOrigin-RevId: 566908824

* Add MimeTypes.EXTERNALLY_LOADED_IMAGE

PiperOrigin-RevId: 566915171

* Fix not setting videoEffect in CompositingVSP

The current code only set the videoEffects when CVSP is initialized, which
happens after `player.prepare()`. But it's valid that videoEffects are set
before calling `prepare()`.

PiperOrigin-RevId: 566941216

* Extract the VideoSinkProvider interface

PiperOrigin-RevId: 566972998

* Add performance playback test for video effects

PiperOrigin-RevId: 567000714

* Move GlProgram.loadAsset to Util and make it public.

PiperOrigin-RevId: 567025091

* Add new setIntsUniform for setting ivec uniforms in shaders.

PiperOrigin-RevId: 567102956

* Move DefaultImageDecoderTest in tests

Move DefaultImageDecoderTest in tests since we can decode images with
Robolectric's native graphics mode.

PiperOrigin-RevId: 567259458

* HDR: Update HdrMode fallback to use OpenGL tone-mapping.

OpenGL tone-mapping is more reliable and widely supported than
MediaCodec tone-mapping.

PiperOrigin-RevId: 567267389

* Bump IMA SDK version to 3.31.0

#minor-change

PiperOrigin-RevId: 567282094

* Session tests: Add missing `CountdownLatch.await()`

This helps deflake this test.

PiperOrigin-RevId: 567288892

* Compositor: Clarify javadoc, to mention VideoCompositorSettings.

Clarify that we use OverlaySettings to place frames over one another,
as passed in via VideoCompositorSettings

PiperOrigin-RevId: 567321828

* Adjust externally loaded image URI MIME type definition

Adjust the Javadoc to highlight that data of this MIME type just contains a URI, not the actual image content.

And also remove the superfluous "key" part of the MIME type string that doesn't
really add information (and it's also really just an URI, not an URI key).

PiperOrigin-RevId: 567560238

* Split VideoGraph interface and move VideoGraph to common

PiperOrigin-RevId: 567599249

* Cross-reference per-stream volume methods from device volume methods

The per-stream methods are generally preferred and having a reference
to them from the device-wide methods may help with discoverability.

Issue: google/ExoPlayer#11295
PiperOrigin-RevId: 567604785

* Use proxy controller to maintain platform session and notification

With this change, the notification controller that is connected by
`MediaNotificationManager`, is used as a proxy controller of the
System UI controller. An app can use the proxy at connection time
and during the lifetime of the session for configuration of the
platform session and the media notification on all API levels.

This includes using custom layout and available player and session
commands of the proxy to maintain the platform session (actions,
custom actions, session extras) and the `MediaNotification.Provider`.

The legacy System UI controller is hidden from the public API,
instead the app interacts with the Media3 proxy:

- System UI is hidden from `MediaSession.getConnectedControllers()`.
- Calls from System UI to methods of `MediaSession.Callback`/
  `MediaLibrarySession.Callback` are mapped to the `ControllerInfo`
  of the proxy controller.
- When `getControllerForCurrentRequest()` is called during an operation of
  System UI the proxy `ControllerInfo` is returned.

PiperOrigin-RevId: 567606117

* Add missing VideoGraph javadoc param

PiperOrigin-RevId: 567621861

* Compositor: Add VideoCompositorSettings to Composition.

This allows apps using Transformer to customize how a Composition is used.

PiperOrigin-RevId: 567633129

* Test: Use timestamp iterator in texture output test.

Simplify tests, before we add some similar tests.

PiperOrigin-RevId: 567666340

* Test: Rename getBitmap to getBitmapAtPresentationTimeUs

PiperOrigin-RevId: 567683139

* Remove static initializer block from `MediaSessionKeyEventTest`

PiperOrigin-RevId: 568149422

* Allow custom methods in Rtsp Options response public header

ExoPlayer will not fail playback if an RTSP server responds to the Options request with an unknown RTSP method request type. ExoPlayer will parse the response and just not call methods it does not know how to use.

Issue: androidx/media#613
PiperOrigin-RevId: 568152076

* Fix 'unused return value' error in `SubtitleViewUtilsTest`

PiperOrigin-RevId: 568170342

* Pass down ControllerInfo from service to session when connecting

With this change, the `ControllerInfo` passed to
`MediaSessionService.onGetSession(ControllerInfo)`
is the same instance that is passed later to all
callback methods of `MediaSession.Callback`.

PiperOrigin-RevId: 568216855

* Resolve and dispatch media button events within Media3

Before this change, media button events are routed from `onStartCommand`
of the `MediaSessionService` to  the `MediaSessionCompat`, resolved by
the legacy library to a session command called on
`MediaSessionCompat.Callback` from where the command is delegated back
to the Media3 session.

With this change the keycode is resolved directly to a Media3 command
that is sent to the session through the media notification controller
of the session.

After this change, a playback or custom command sent to the session
from a notification, either as a pending intent (before API 33) or as
a legacy session command, look the same and the caller is the
media notification controller on all API levels.

PiperOrigin-RevId: 568224123

* Update VideoSink `queueBitmap()` to match VideoFrameProcessor

PiperOrigin-RevId: 568226567

* Update decode-only flag logic in non-MediaCodec-renderers

MediaCodecRenderer has already been updated to not rely on the
input stream to mark its samples as decode-only and instead use
a simple time-based comparison to achieve the same effect.

This change makes the same update for all other renderers that
either use the flag directly or forward to a "decoder" instance.

PiperOrigin-RevId: 568232212

* Set SurfaceView lifecycle to follow attachment in PlayerView

This avoids destroying the surface if PlayerView is hidden in the
view hierarchy.

PiperOrigin-RevId: 568501459

* Verify a thread is alive before sending a message to it.

PiperOrigin-RevId: 568515736

* Add new APIs to ExoMediaDrm

Changes
---
- Added `removeOfflineLicense(byte[])` and `getOfflineLicenseKeySetIds` and consumed them in their implementations

Background
---
- These APIs will help in addressing an increasing amount of `java.lang.IllegalArgumentException: Failed to restore keys: BAD_VALUE` which is our top playback error in our app
	- Based on our discussion with Widevine team and [this exoplayer issue](https://github.com/google/ExoPlayer/issues/11202#issuecomment-1708792594)
		- TL;DR: The failure occurs on startup if the user has 200+ offline licenses, we would like to add the functionality to remove offline licenses

**Note: Why we want these APIs in ExoMediaDrm and not in OfflineLicenseHelper**
	- As per the issue above, we would like to access these 2 public APIs in MediaDrm that don’t exist in `OfflineLicenseHelper` or `ExoMediaDrm`
		- APIs interested in:
			- [MediaDrm#removeOfflineLicense()](https://developer.android.com/reference/android/media/MediaDrm#removeOfflineLicense(byte%5B%5D)): To remove offline license
			- [MediaDrm#getOfflineLicenseKeySetIds()](https://developer.android.com/reference/android/media/MediaDrm#getOfflineLicenseKeySetIds()): To see number of offline licenses on startup

		- We use `OfflineLicenseHelper` to download license for L1 and we don't interact with `ExoMediaDrm` directly. But for the alternate Widevine integration, we directly depend on `ExoMediaDrm` APIs to override and call CDM Native APIs.
		- We would like to have the functionality of removing offline licenses for both integration which would need access to above APIs in `ExoMediaDrm`.

Links
---
- https://github.com/androidx/media/issues/659

* Reformat some javadoc and use Guava empty list

* Change the DASH playback dump for webvtt in mp4 to include subtitles

#minor-release

PiperOrigin-RevId: 568567703

* Limit SequenceAssetLoader variable scope.

All usages of these variables are within the SampleConsumerWrapper,
so limit them to that scope.

PiperOrigin-RevId: 568582645

* Update dumpfile tests to only print ColorInfo fields that are set

PiperOrigin-RevId: 568789489

* Throw Exception if posting to application handler fails.

PiperOrigin-RevId: 568799683

* Mark HEIF decoding as only supported on API 26+

https://developer.android.com/guide/topics/media/platform/supported-formats#image-formats

#minor-release

PiperOrigin-RevId: 568864219

* Add position interpolation to MediaControllerImplLegacy

Without this, the position won't udpate until the session sends
a new playback state.

PiperOrigin-RevId: 568889286

* Test: Update HDR GL tone-map fallback string.

PiperOrigin-RevId: 568920716

* Add default implementation of Callback.onSubscribe

The library already maintains the subscribed controllers internally. This
change adds `MediaLibrarySession.getSubscribedControllers(mediaId)` to
access subscribed controllers for a given media ID.

To accept a subscription, `MediaLibraryService.Callback.onSubscribe` is
required to return `RESULT_SUCCESS`. So far, this isn't the case for the
default implementation of the library.

This change implements `Callback.onSubscribe` to conditionally
provide `RESULT_SUCCESS`. The default calls `Callback.onGetItem(mediaId)` to
assess the availability of the media item. If the app retruns `RESULT_SUCCESS`
with a browsable item, the subscription is accepted. If receiving a valid item
fails, the subscription is rejected.

Issue: androidx/media#561
PiperOrigin-RevId: 568925079

* Add isAutomotiveController and isAutoCompanionController

Issue: androidx/media#561
Issue: androidx/media#644
Issue: androidx/media#645
PiperOrigin-RevId: 568948230

* Split demo service into its own module for reuse

To support Automotive with the session demo, we need a separate app module.
To do this we need to split the service into its own module and make it
usable from different modules.

PiperOrigin-RevId: 568975271

* Update release notes for 1.2.0-alpha02

PiperOrigin-RevId: 569161165

* Suppress lint in `PlayerControlView` and `TrackSelectionDialogBuilder`

PiperOrigin-RevId: 569165562

* Fix review comments

* Move Single/MultiVideoGraph impl to effect

PiperOrigin-RevId: 569188658

* Mark `DefaultImageDecoder.BitmapDecoder` as `@VisibleForTesting`

It seems likely we will define a new "image decoder" interface that
returns `ListenableFuture<Bitmap>`, and naming that will be
hard/annoying if we need to keep this interface working too.

It's also not really clear what a non-test implementation of this
interface would be expected to do, since `DefaultImageDecoder` is
documented to always decode using `BitmapFactory`.

#minor-release

PiperOrigin-RevId: 569206325

* Bump Media3 version numbers for 1.2.0-alpha02

PiperOrigin-RevId: 569269992

* Add demos/session-automotive module

This change also enables Android Auto support for the
session demo.

PiperOrigin-RevId: 569448376

* ExportTest: make 8K asset and trim

Move remote 8K file to local and trim to 320ms.

Trim done with ffmpeg:

`ffmpeg -i {remote_file} -t 0.3 -c:v copy -c:a copy 8k24fps_300ms.mp4`

PiperOrigin-RevId: 569449962

* Add previewing specific video graph.

PiperOrigin-RevId: 569473178

* Rename `DefaultImageDecoder` to `BitmapFactoryImageDecoder`

This reflects the documented behaviour of this class.

#minor-release

PiperOrigin-RevId: 569475137

* Remove FfmpegVideoRenderer from Media3 1.2.0 release

* Update playlist UI when playlist is updated

When changing the playlist on Android Auto the UI of the
activity needs to be kept in sync.

PiperOrigin-RevId: 569528785
(cherry picked from commit 52d9fbff73cddd5c0881f6fd53a6ba35220d0ed1)

* Mark test_session_current support app as MultiDexApplication

PiperOrigin-RevId: 570015354
(cherry picked from commit e9bf41ca044368f6833984a38b0f7804ce9b1960)

* MediaCodeVideoRenderer: flush video sink before codec

When seeking, we must first flush the video sink so it stops
using any SurfaceTextures before flushing MediaCodec.

#minor-release

PiperOrigin-RevId: 570015998
(cherry picked from commit 144bd7223626a2936368cbcb3bf3f7004ebe5e45)

* Merge pull request #574 from hugohlln:main

PiperOrigin-RevId: 570037211
(cherry picked from commit b06d82323865870e5c3572e867d3cc165200e497)

* Fix `Util.scaleLargeValue/Timestamp` to handle negative numbers

#minor-release

PiperOrigin-RevId: 570337535
(cherry picked from commit 9edbfa974aeab851065655e09e8c1accf51a009c)

* Deprecate experimental keepAudioTrackOnSeek methods.

#minor-release

PiperOrigin-RevId: 570340714
(cherry picked from commit 1bb501ab5046cfb7c9e21302cd3a0d73c176512c)

* Explicitly mark DecoderOutputBuffer as shouldBeSkipped if needed

In some cases, SimpleDecoder output needs to be skipped for rendering
because the decoder produces no data. This is one of the remaining
usages of BUFFER_FLAG_DECODE_ONLY at the moment and can be more
directly solved without using the flag. SimpleDecoder still needs to
check the flag though for backwards compatbility with custom decoders
while the flag is not completely removed.

PiperOrigin-RevId: 570345233
(cherry picked from commit c8aac24ffd8bfe708d68a251a9f28b3b48bed50c)

* Add Dumper support for outputting multiline strings

PiperOrigin-RevId: 570348425
(cherry picked from commit b83f12c4ba5f7adac388f003596214b03d1d9358)

* Add DashPlayback test with sideloaded TTML subtitles

The test is hidden behind the Ignore annotation due to some flakiness just like `webvttInMp4`. However, it will be removed when the subtitle parsing is moved to a pre-sample-queue architecture.

#minor-release

PiperOrigin-RevId: 570376275
(cherry picked from commit bd5a3920b85423f1c1b625369fd606a9f36e1248)

* Disable offload scheduling at set up for track transition

While sleeping for offload, position is estimated based on time playing. If asleep and AudioTrack is reused, then the position will keep incrementing as the subsequent item plays. That is until wakeup when playing position is updated to the timestamp of the second item. Offload scheduling should be disabled until track transitions fully.

PiperOrigin-RevId: 570397140
(cherry picked from commit da06bf057a230293c8fb7f06cbfba71df8c4b5b1)

* Move decode-only handling out of MetadataDecoder interface logic

The interface requires the implementation to return null if the
decode-only flag is set. So instead of setting the flag and returning
null, we can simply not call the method and assume it's null.

The only reason where this wouldn't work is if the metadata format
has keyframe-like logic and requires previous metadata to decode
the next one. This is not something we came across before and it seems
ignorable. If that feature is needed in the future, we should instead
add a method to MetadataDecoder to set the first output timestamp.

#minor-release

PiperOrigin-RevId: 570399838
(cherry picked from commit 796781d4c365e31a196c96e0588e4ff5ff0e3bf0)

* Add nullness annotations to `MediaCodecRenderer`

#fixit

PiperOrigin-RevId: 570403923
(cherry picked from commit 7a91474af9f84595743655b18f4164e193bf2fc1)

* Add nullness annotations to `DecoderVideoRenderer`

Also fixed a bug where format queue was polled with wrong timestamp value.

#fixit

PiperOrigin-RevId: 570420304
(cherry picked from commit a879bae1ee2c684e8100f50bcff39655d46a2e8d)

* Add onAudioTrackInitialized/Released events

This is useful for analytics and understanding player behavior
during transitions.

#minor-release

PiperOrigin-RevId: 570623227
(cherry picked from commit 8e2bf21011c63e2ca2fc58c4353cd66930b621e3)

* Update getName of BitmapFactoryImageDecoder

cleanup from https://github.com/androidx/media/commit/8f5835c51c0d0e4221a1de68b6638c910b911264

#minor-release

PiperOrigin-RevId: 570663437
(cherry picked from commit 572fb4676cd8ce5b40c8ab044aeb2250390f1c17)

* Replace ENCODING_DTS_UHD_P2 value by reference to platform constant

#minor-release

PiperOrigin-RevId: 570696505
(cherry picked from commit 9ef1c20e7af4cc483e3ab408218545b182c1a28e)

* Remove wrong Javadoc

The corresponding logic has been removed in https://github.com/androidx/media/commit/796781d4c365e31a196c96e0588e4ff5ff0e3bf0

#minor-release

PiperOrigin-RevId: 570729509
(cherry picked from commit 64fe863f315bbc870b347c4d9ea8009fb7713773)

* Add Decoder.setOutputStartTimeUs and use it in extension decoders

This gets rid of the reliance on the decode only flag that is still
set on input buffers to the decoder if they are less than the start
time.

We still need to set and check the decode-only flag in SimpleDecoder
to ensure compatbility with custom decoders that use the flag while
it's not fully removed.

PiperOrigin-RevId: 570736692
(cherry picked from commit a03e20fe6c423389d54eb08d3b1f1d19499a0d9a)

* Add `CuesWithTiming.endTimeUs`

In most cases this is more useful than `durationUs`.

We will keep `durationUs`, and the constructor will continue to take
`startTimeUs` and `durationUs`, to allow for use-cases where we don't
know the start time but still want to indicate a duration (this will be
used to implement CEA-608 timeout).

#minor-release

PiperOrigin-RevId: 570944449
(cherry picked from commit bf7b91e57e477f71644d5e585e0e999deadf7fa3)

* Use RTSP Setup response timeout value in KeepAliveMonitor intervalMs

Set KeepAliveMonitor to send a keep-alive message at half the timeout value, if provided, by the RTSP Setup response.

Issue: androidx/media#662
PiperOrigin-RevId: 570946237
(cherry picked from commit 42c1846984fc8ebca5cdbdcf6df8d2dca44eea96)

* Remove experimental keepAudioTrackOnSeek.

PiperOrigin-RevId: 570966027
(cherry picked from commit 068d420ba2d27847c5c581d851ff6a5e1ec45611)

* Update documentation wrongly referencing the decode-only flag

#minor-release

PiperOrigin-RevId: 570973457
(cherry picked from commit 87f1b4252ec2d342a153e49aac19455cb91655d1)

* Change equalTo check in ImagePlaybackTest to atLeast

The aim of this test is to make sure the image is onscreen for the right amount of time, so to drive down flakes from the decoder taking too long, change this to an atLeast check

#minor-release

PiperOrigin-RevId: 570988044
(cherry picked from commit 9cc75ca52e49792bed43e4d8fbf67b9a0576fdc0)

* Add tests for `CuesWithTiming.endTimeUs`

#minor-release

PiperOrigin-RevId: 570988195
(cherry picked from commit 6057b59723ce6e45ec8a68007eff6687956a9a73)

* Remove release notes lines added by merge conflict

#minor-release

PiperOrigin-RevId: 571005643
(cherry picked from commit 49b1e0bbc2a82f3b9c6ba0a1696ee0b1e53673ec)

* Deprecate decode-only flag.

The flag is no longer used by our components and only set and checked
in a few places to guarantee compatiblity with existing renderers and
decoders that still use it.

The flag will be removed in the future due to its design limitations.

#minor-release

PiperOrigin-RevId: 571291168
(cherry picked from commit 89d01981bc4cf9218e73bcce1b52c7afe29fbecd)

* Add MEDIA_PLAY_FROM_SEARCH to manifest of session demo app

This is required to make GMS send voice commands to the app.

#minor-release

PiperOrigin-RevId: 571326122
(cherry picked from commit 78f403aa7b795e0e3bcd2f4682bef171f545d4fa)

* Allow pause if in offload mode after writing all buffers

In offload mode, `AudioTrack#stop()` will put the track in `PLAYSTATE_STOPPING` rather than `PLAYSTATE_STOPPED`. The difference in state means that `AudioTrack` can be paused and played during this 'stopping' period.

Currently, if `AudioTrackPositionTracker#handleEndOfStream()` has been called then `DefaultAudioSink` in `pause()` won't call `AudioTrack#pause()`. `AudioTrack#pause()` should be called in this case if in offload mode.

#minor-release

PiperOrigin-RevId: 571335108
(cherry picked from commit ab42d64d6d5f1859f1c45aebfe26060978b864bd)

* Update cached playbackHeadPosition when pausing after AudioTrack.stop()

In some streaming scenarios, like offload, the sink may finish writing buffers a bit before playback reaches the end of the track. In this case a player may pause while in this 'stopping' state.

The AudioTrackPositionTracker needs to update the cached values it uses to calculate position in the `PLAYSTATE_STOPPED`/`PLAYSTATE_STOPPING` states if pause/play are called during this period.

PiperOrigin-RevId: 571345914
(cherry picked from commit a789db5b41d9d7a671e83a488b3dec372eaa8b3d)

* Add multidex Gradle dependency to test-session-current

#minor-release

PiperOrigin-RevId: 571347856
(cherry picked from commit e63be0317f2152398174bb01c3ea134a0883da10)

* Deflake RTSP keep-alive monitor test

Alters RTSP KeepAlive monitor test to just make sure that keep-alive message is sent.

The test was added in https://github.com/androidx/media/commit/42c1846984fc8ebca5cdbdcf6df8d2dca44eea96

#minor-release

PiperOrigin-RevId: 571349013
(cherry picked from commit 417970f7132ab9fd539ba692309e29050b7001d5)

* Bump Media3 version numbers for 1.2.0-beta01 release

#minor-release

PiperOrigin-RevId: 572003628
(cherry picked from commit 97645a200d6abcdbacd1805ef149b5f2b02943c0)

* Update RELEASENOTES.md for 1.2.0-beta01 release

PiperOrigin-RevId: 571941830
(cherry picked from commit 62ad1dfdf5699b72f5f218c9cabcf73fb1a9f070)

* Rollback of https://github.com/androidx/media/commit/64bd3bcad3fa4b0e433b16d583456920afad3ce2

PiperOrigin-RevId: 574766164
(cherry picked from commit f0cab4d03ecfa7fbd48262c332d85329736224af)

* Do not hide System UI when app rejects connection

If an app rejects the connection of the internal media notification manager
the session should behave like without the the media notification controller.
The legacy System UI controller should not be hidden or even rejected to
connect in such a case.

#minor-release

PiperOrigin-RevId: 574807901
(cherry picked from commit 54d5810fc353a9e7133ef929ab2f822d921070b1)

* Merge pull request #728 from lawadr:audio-capabilities-fix

PiperOrigin-RevId: 574829263
(cherry picked from commit 5f80a4708165ffe977ce37400f7c8eae01142e2d)

* Add missing command checks to playback resumption flow

Player methods shouldn't be called if they are not available and the
entry point to the playback resumption flow only checks
COMMAND_PLAY_PAUSE.

#minor-release

PiperOrigin-RevId: 574834148
(cherry picked from commit bfd1a2724c660de0df3c13f8394238ac6aa26e68)

* Remove CompositionPlayer activity from the transformer demo app

The CompositionPlayer is not ready yet.

Issue: androidx/media#741
PiperOrigin-RevId: 574859927
(cherry picked from commit beb1711d4cfad51b88016bbb2b1e0f1a7945ed84)

* Update translations in the ui module

#minor-release

PiperOrigin-RevId: 575161190
(cherry picked from commit a8ab9e2c70c98ee65e3b3d71806da6c9fc5c42e3)

* Use MediaSessionImpl.onMediaButtonEvent() to dispatch key events

This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: androidx/media#12
Issue: androidx/media#159
Issue: androidx/media#216
Issue: androidx/media#249

#minor-release

PiperOrigin-RevId: 575231251
(cherry picked from commit a79d44edc5c7fdc81120dbc9b2c89b9799b14031)

* Update `TextRenderer` to handle `CuesWithTiming` instances directly

The existing `Subtitle` handling code is left intact to support the
legacy post-`SampleQueue` decoding path for now.

This also includes full support for merging overlapping `CuesWithTiming`
instances, which explains the test dump file changes, and which should
resolve the following issues (if used with the
decoder-before-`SampleQueue` subtitle logic added in
https://github.com/androidx/media/commit/5d453fcf37b52a9ea4182f266d60f3bf8e3318c2):

* Issue: google/ExoPlayer#10295
* Issue: google/ExoPlayer#4794

It should also help resolve Issue: androidx/media#288, but that will also require
some changes in the DASH module to enable pre-`SampleQueue` subtitle
parsing (which should happen soon).

PiperOrigin-RevId: 571021417
(cherry picked from commit 002ee0555dc35dce9570f1a991b33ec92743db10)

* Return true from `CuesResolver.addCues` if the output changed

This belongs in the resolver, because it depends on the resolution
algorithm (and therefore the logic can't live in `TextRenderer`).

This also fixes a bug in `TextRenderer` where we were doing arithmetic
with `cues.durationUs` without checking if it was `TIME_UNSET` first.

#minor-release

PiperOrigin-RevId: 571332750
(cherry picked from commit 272428734b79ac6857a4333ede2b12563f8b78de)

* Report dropped frames from the VideoSink

After https://github.com/androidx/media/commit/4fad529433011d280f1e5ebd4465808ef60c2d77, MediaCodecVideoRenderer does not report if frames
are dropped from the VideoSink. This commit fixes this.

#minor-release

PiperOrigin-RevId: 571905721
(cherry picked from commit 05b17b543060c1f32ae7af212e5e8b33203bdadd)

* Fix the asset and dump file names for the standalone TTML DASH test

#minor-release

PiperOrigin-RevId: 571941997
(cherry picked from commit 33c151eb5b5ce85e554215af0c1d860b66c66fab)

* Use more targeted listening in session PlayerActivity

The current metadata updates are triggered by item transitions,
but depending on the speed of loading the playlist, the first
metadata may only be known later via metadata-change callbacks.

Slow playlist loading also means the UI stays empty and it's
beneficial to show a placeholder to avoid the impressions the
UI hangs.

Finally, clean-up by removing unused string constants and merging
all listeners into onEvents

#minor-release

PiperOrigin-RevId: 571951529
(cherry picked from commit fd81c904e11c47dcd7694e9b2f610914d4cf2596)

* ...Update metalava library and Reformat api.txt...

PiperOrigin-RevId: 572013340
(cherry picked from commit da49a02b44365d6f85d5191ccb9c6df05d01fd3c)

* Fix the resumption of playback when suitable device is connected.

With this change the playback will resume as soon as the suitable device is connected and suppression reason is cleared (within set time out).

#minor-release

PiperOrigin-RevId: 572140309
(cherry picked from commit dc859eae82767598c43bbb182e81228be55f030b)

* Add missing Future cancellation checks

Future.isDone and getDone doesn't imply the Future was successful
and it may have been cancelled or failed.

In case where we handle failure, we should also handle cancellation
to avoid CancellationException to bubble up unchecked.

In demo app code where we use isDone for field initialization, we
want to crash in the failure case (usually security exception where
the connection is disallowed), but we want to gracefully handle
cancellation. Cancellation of these variables usually happens in
Activity.onDestroy/onStop, but methods may be called after this point.

#minor-release

PiperOrigin-RevId: 572178018
(cherry picked from commit fe7c62afe0b39f8d6617cf610dbdccc9e6adcfb4)

* Make BundleListRetriever local Binder aware

When used within the same process, we don't have to go via the
onTransact method (which includes marshalling and unmarhsalling
the data), but can directly return the list.

#minor-release

PiperOrigin-RevId: 572179846
(cherry picked from commit 0bddd06938fb5dc97a99a0cb3a444815a47be41c)

* Use package-level `@OptIn` for demo apps

This demonstrates that `@OptIn` can now be used at the package-level
(since [`androidx.annotation:annotation-experimental:1.3.0`](https://developer.android.com/jetpack/androidx/releases/annotation#annotation-experimental-1.3.0)).

PiperOrigin-RevId: 572187729
(cherry picked from commit d60596cfca2926f851881be871117c7772e7096c)

* Align audio adaptive support checks with video

In particular:
 - Add allowAudioNonSeamlessAdaptiveness parameter (default true, same
   as video and as already implemented by default)
 - Forward mixedMimeTypeAdaptation support to AudioTrackScore
   (as for VideoTrackScore) and adapt mixed MIME type adaptive
   support accordingly
 - Check adaptive support when deciding whether a track is allowed for
   adaptation (also same check as for video). This takes the new
   parameter into account.

PiperOrigin-RevId: 572191308
(cherry picked from commit f20d18e6cae136f8109380d69be76178008cdc17)

* Remove unneccessary method parameter

The value already exists as a class field.

#minor-release

PiperOrigin-RevId: 572200771
(cherry picked from commit e5fa0c2ce98930e4b679576290b5c0bebd37ad21)

* Add `SubtitleParser.Factory.getCueReplacementBehavior()`

This gives access to the replacement behavior for a particular subtitle
format without needing to instantiate a `SubtitleParser`.

#minor-release

PiperOrigin-RevId: 572226084
(cherry picked from commit e366c3d419f487beb567e360c21400c31add477f)

* Update `@UnstableApi` docs to include a `package-info.java` example

#minor-release

PiperOrigin-RevId: 572229092
(cherry picked from commit 7009c53c799171c4f8e418af5fdb31a6a5544ab9)

* Do not interrupt controller thread without a good reason

Interrupting the main thread in particular may be dangerous
as the flag is not cleared after handling the current message.

#minor-release

PiperOrigin-RevId: 572259422
(cherry picked from commit 846117399ff87dc025c355639444de2e54430b18)

* Add experimental opt-in to parse DASH subtitles during extraction

This currently only applies to subtitles muxed into mp4 segments, and
not standalone text files linked directly from the manifest.

Issue: androidx/media#288

#minor-release

PiperOrigin-RevId: 572263764
(cherry picked from commit 66fa5919590789b384506a4e604fe02a5a5e0877)

* Add MediaSession.Builder().setPeriodicPositionUpdateEnabled()

This allows to disable periodic position updates when building
the session.

#minor-release

PiperOrigin-RevId: 572531837
(cherry picked from commit 4dc3db4da3da486b9c9ec1780aa595da8de5330c)

* Request notification permission when starting session demo app

#minor-release

PiperOrigin-RevId: 572556101
(cherry picked from commit c7a091a97373d3009074dba7ec0eeaaae79b1a12)

* Update release notes to mention AudioOffloadPreference class changes

Issue: androidx/media#721
PiperOrigin-RevId: 572565009
(cherry picked from commit cef85be40f11f129f38bb19438721236c164c9bf)

* Check whether a session is still managed before removing

When the controller of the `MediaNotificationManager` is disconnected,
the session is removed from the service without checking whether the
session hasn't already been removed. This caused flakiness in `MediaSessionServiceTest.addSession()`.

Because there is a public API `MediaSessionService.removeSession()`,
the controller can't make an assumption whether the session is still
contained in the service when being disconnected.

#minor-release

PiperOrigin-RevId: 572568350
(cherry picked from commit 7fdc5b22bac1af6fd074df38bb6b98c921e713a1)

* Split available command filtering and bundling

A few methods in PlayerInfo and related classes combine filtering
information with bundling in one method. This makes it impossible
to use just the filtering for example and it's also easier to reason
about than two dedicated methods. This change splits these methods
into two parts accordingly.

PiperOrigin-RevId: 572592458
(cherry picked from commit 4ebe630a80296cbb4437336a50abccb39da978f7)

* Avoid bundling PlayerInfo for in-process calls

PlayerInfo bundling is costly and we can add a shortcut for
in-process binder calls where we store the direct object
reference in a live Binder object that can be written to the
Bundle instead of the individual data fields.

#minor-release

PiperOrigin-RevId: 572816784
(cherry picked from commit d1fc15f2075dd5c130a12420889fd83bd6517a08)

* Migrate `SubtitleParser` tests to incremental `parse()` methods

All the production code is already calling these new incremental
methods, migrating the tests allows us to remove the old
`List`-returning methods in a follow-up change.

#minor-release

PiperOrigin-RevId: 572822828
(cherry picked from commit a12bde4f57002a9adf5da6c01b2f601a6edf92e9)

* Merge pull request #650 from cedricxperi:dts-lbr-buffer-underflow-fix

PiperOrigin-RevId: 572864175
(cherry picked from commit 2421ba4d8fec6ef805f2765f522d4bf0027a08c9)

* Change `LegacySubtitleUtil` handling of `SubtitleParser.OutputOptions`

If the `Subtitle` has 'active' cues at `OutputOptions.startTimeUs`, this
change ensures these are emitted in a `CuesWithTiming` with
`CuesWithTiming.startTimeUs = OutputOptions.startTimeUs`. If
`OutputOptions.outputAllCues` is also set, then another `CuesWithTiming`
is emitted at the end that covers the 'first part' of the active cues,
and  ends at `OutputOptions.startTimeUs`.

As well as adding some more tests to `LegacySubtitleUtilWebvttTest`,
this change also adds more tests for `TtmlParser` handling of
`OutputOptions`, which transitively tests the behaviour of
`LegacySubtitleUtil`.

#minor-release

PiperOrigin-RevId: 573151016
(cherry picked from commit f9ece88a25b449ab1e59ec0f6a67b71d7a2dc8ce)

* Remove the 'super speed' SmoothStreaming PlayReady stream from demo

This content is no longer available, the manifest is returning a 404.

Issue: google/ExoPlayer#11309

#minor-release

PiperOrigin-RevId: 573202175
(cherry picked from commit a19f577976fc670c47e837d521c48170ab900ea0)

* Migrate `SubtitleParser` implementations to incremental `parse()`

All production and test callers of the non-incremental methods are
already migrated, so we can remove them in this change too.

#minor-release

PiperOrigin-RevId: 573207318
(cherry picked from commit ecd24646cb1fd4b06a27cfe87ec0df47e9db87ed)

* Test more URI forms in `RawResourceDataSourceContractTest`

PiperOrigin-RevId: 573220915
(cherry picked from commit 40459f72123cfc3bbead5dd42ce2aa3a824155b2)

* Remove deprecated `DownloadNotificationHelper.buildProgressNotification`

Use a non deprecated method that takes a `notMetRequirements` parameter
instead.

PiperOrigin-RevId: 573252909
(cherry picked from commit 8b7ebc70320e66b6360df37c36d4cfc2fb71aa98)

* Calculate HLS live playlist refresh interval accurately

Previously, we calculated the next playlist reload time by adding the target duration (or half of it, depending on whether there is a real update in the new playlist snapshot) from the last load completion time, which makes the reload interval as long as `targetDuration(or half of it) + lastLoadDuration`. While still complying to the standard that "the client MUST wait for at least the target duration before attempting to reload the Playlist file again", this could cause buffering when the playback position is close to the end of live window. This change is to calculate the reload interval accurately by not adding the term `lastLoadDuration`.

Issue: androidx/media#663

#minor-release

PiperOrigin-RevId: 573300009
(cherry picked from commit 58a63c82aa0b59e86a656cf6644781a1c4690c82)

* Expand MediaItems in session demo instead of just replacing them

When MediaItems are added from the controller, we currently completely
replace the item with the one from our database, overriding any
potential additional information the controller may have set.

Also forward the onAddMediaItems/onSetMediaItems callbacks to common
helper methods instead of redirecting them through super methods

#minor-release
Issue: androidx/media#706
PiperOrigin-RevId: 573799351
(cherry picked from commit 00425dbe80dc9da38766f7235052c434d79724d1)

* Only set the queue when COMMAND_GET_TIMELINE is available

Android Auto shows a queue button when the queue is not empty.
Apps were able to remove this queue button with the legacy API
by not setting the queue of the session.

After this change, removing `COMMAND_GET_TIMELINE` from the commands
of the media notification controller or the session player sets the
queue in the platform session to null.

#minor-release
Issue: androidx/media#339
PiperOrigin-RevId: 573813558
(cherry picked from commit f53e1bc6f63caba7774c35aeb663b9178941faf5)

* Send `ConnectionState` as in-process bundle if possible

#minor-release

PiperOrigin-RevId: 573849858
(cherry picked from commit d5f093f43cc2bda763436d4ecf32c38c76b9418e)

* Send media button events from service directly using `MediaSessionImpl`

Media button event coming from the `MediaSessionService` are delegated
to the `MediaSessionImpl` and then sent to the session by using the
`MediaSessionStub` directly instead of using the `MediaController`
API.

Splitting the `MediaController.Listener` and `Player.Listener` in
`MediaNotificationManager` got reverted, and both listener are set to the
controller as before. This reverts the change that introduced a
different timing behaviour. It still holds, that a listener
registered on a `MediaController` that calls a method like `play()` is
called immediately and before the call has arrived at the player. This
change works around this behaviour from the library side by calling
`MediaSessionStub` directly with a `ControllerInfo`.

#minor-release

PiperOrigin-RevId: 573918850
(cherry picked from commit 64bd3bcad3fa4b0e433b16d583456920afad3ce2)

* Move DASH subtitle parsing release note to correct section

#minor-release

PiperOrigin-RevId: 574090381
(cherry picked from commit df19097e220f7b4599830bc2a802b0951bc71cfb)

* Merge pull request #491 from v-novaltd:dsparano-exo128

PiperOrigin-RevId: 574129451
(cherry picked from commit 009d48a75e932c9e8e94a28ca2b92970cf5fe357)

* Publish MIDI decoder module on Maven repository

Issue: androidx/media#734

#minor-release

PiperOrigin-RevId: 574182702
(cherry picked from commit 61770f8a61312cacf596536b614eeb49f6abab6e)

* Rollback of https://github.com/androidx/media/commit/64bd3bcad3fa4b0e433b16d583456920afad3ce2

PiperOrigin-RevId: 574290408
(cherry picked from commit 1a43aa3602075cc88c902de293cb025ff3d619cc)

* Rollback of https://github.com/androidx/media/commit/4ebe630a80296cbb4437336a50abccb39da978f7

PiperOrigin-RevId: 574308136
(cherry picked from commit ff330bd8e9e925987396597cfa25f5455e1d4048)

* Fix MIDI decoder build.gradle

Issue: androidx/media#734

#minor-release

PiperOrigin-RevId: 574425269
(cherry picked from commit ff4ff76990b52718f8c1e4acd9075c5c06ebee0e)

* Use DataSourceBitmapLoader by default

This replaces the SimpleBitmapLoader that can now be deprecated
as it's fully unused and doesn't provide any additional functionality.

#minor-release

PiperOrigin-RevId: 574454636
(cherry picked from commit db86932781b4a5f377d1f4c1414c3d6a74ede174)

* Send decode-only Opus samples in bypass mode for seekPreRoll skip

As Opus decoders skip some bytes prior to playback during a seek, the renderer for bypass playback should send samples to the decoder even if they would be decode-only.

#minor-release

PiperOrigin-RevId: 574494666
(cherry picked from commit 00193e0304a5ea2c20012fabf77f82f29e218372)

* Add formatting to `scheme` list in `DefaultDataSource` javadoc

The current formatting makes the 'scheme' part of the list blend into
the definition, especially when the definition is multi-line.

https://developer.android.com/reference/androidx/media3/datasource/DefaultDataSource

I considered adding another level of nesting, but I think bold will
help distinguish the structure of the list without adding too much HTML
or visual whitespace.

#minor-release

PiperOrigin-RevId: 574514208
(cherry picked from commit aec6db77faba617dc2ab225b72c9bc3350c5b5c3)

* Rollback of https://github.com/androidx/media/commit/4ebe630a80296cbb4437336a50abccb39da978f7

PiperOrigin-RevId: 574530273
(cherry picked from commit c0759a4e62466bbc0816737e28adf1b4a513016c)

* Rollback of https://github.com/androidx/media/commit/eafe2e35f0f343d95b95769dc273d016c20fe3c6

PiperOrigin-RevId: 574755143
(cherry picked from commit cf3733765c2ca59ef2261b2e59b21fae5e7546eb)

* Update RELEASENOTES for 1.2.0-rc01 release

PiperOrigin-RevId: 575795800
(cherry picked from commit 7202f5d4de6a51b3fe23994c49ad8c15350d260c)

* Bump Media3 version numbers for 1.2.0-rc01

#minor-release

PiperOrigin-RevId: 575805495
(cherry picked from commit 9d3d7abdc6460bcc6f01145bcb3ce1e854b86a1a)

* Reorder RELEASENOTES to move unreleased changes to correct section

PiperOrigin-RevId: 575807109
(cherry picked from commit 105bdf57d80e32d8c0d8c4e2598b9c43c9461870)

* Add `com.github.philburk:jsyn` to JAR list

#minor-release

PiperOrigin-RevId: 576148893
(cherry picked from commit 00943a0a734e55a1dbdf584c1bc139ed4db67e64)

* Rollback of https://github.com/androidx/media/commit/a19f577976fc670c47e837d521c48170ab900ea0

PiperOrigin-RevId: 577139027
(cherry picked from commit dd6306e1ba5e860d7a267a0ad3a16eb028e8fd7a)

* Bump media3 versions to 1.2.0 (stable)

#minor-release

PiperOrigin-RevId: 580856330
(cherry picked from commit 3918d3620052138f0d7718cd8076e7389222572d)

* Merge release notes for media3 1.2.0 stable release

PiperOrigin-RevId: 580923121
(cherry picked from commit 7ee07a5ff583e8d56e34783dc4ecfdb7d9a65ef5)

* Add `@OptIn` to fields in demo `PlayerActivity` now this is supported

This is possible now we use `annotation-experimental:1.3.1`.

#minor-release

PiperOrigin-RevId: 582315579
(cherry picked from commit 8d83d491f198fbe3a21181df235dfff314252929)

* Remove recommendation to pin `annotation-experimental` to version 1.2.0

This was intended to avoid bringing in a transitive dependency on the
Kotlin standard library, but Gradle no longer flags lint errors on
`@RequiresOptIn` violations with `annotation-experimental:1.2.0` (1.3.0
is needed), making this recommendation dangerous. See also
https://issuetracker.google.com/310651921.

PiperOrigin-RevId: 582276430
(cherry picked from commit aa1ec981a3eea59f8be9d44104d0573a60816436)

* Clean-up multi-line strings in YAML issue templates

* If we don't want any newlines in the result, it's better to use `>`
* If we want newlines (e.g. for markdown) then we should ensure the
  string **only** contains the newlines we want, because GitHub (unlike
  other markdown renderers) preserves single newlines in the output,
  leading to ugly newlines dictated by the source.

Also remove a markdown-style link that isn't renderered as markdown.

PiperOrigin-RevId: 590309749
(cherry picked from commit 6aeaad26addee2d5793a624526d1811b8973c4ce)

* Fallback to legacy sizerate check for H264 if CDD PerfPoint check fails

Some devices supporting Performance Points for decoder coverage are missing coverage over the CDD requirements for H264. For these cases ExoPlayer should fall back to legacy resolution and frame rate support checks. If there is an H264 stream evaluated as a `PerformancePointCoverageResult` of `COVERAGE_RESULT_NO`, then ExoPlayer checks for coverage of the [720p CDD requirement](https://source.android.com/docs/compatibility/10/android-10-cdd#5_3_4_h_264).

Issue: google/ExoPlayer#10898

Issue: androidx/media#693
PiperOrigin-RevId: 575768836
(cherry picked from commit 4515a0c3f24706a43b3247b558b14d98f2b0fce2)

* Bump okhttp dependency to 4.12

Issue: androidx/media#768
PiperOrigin-RevId: 577208115
(cherry picked from commit e8cca688ad39590a9537c940ed0db4ca805f0fb8)

* Remove stray parentheses from release notes

PiperOrigin-RevId: 577809964
(cherry picked from commit db1ab1dcf37a484370c33b399c52f4e9569c793d)

* Put the custom keys in MediaMetadataCompat to MediaMetadata.extras

PiperOrigin-RevId: 578473874
(cherry picked from commit 84022eacc560b90cf34253b2470aabdf4a4b767d)

* Add warning log if DASH manifest contains incomplete ClearKey info

Unfortunately we can't fail any more obviously at this point, because
manifests often contain config for multiple DRM schemes, and when
parsing the manifest we don't know which scheme is going to be used for
playback. It would be unreasonable to fail playback due to incomplete
ClearKey config if playback was otherwise going to succeed using e.g.
Widevine.

* Issue: androidx/media#777
* Issue: androidx/media#563
* Issue: google/ExoPlayer#9169

#minor-release

PiperOrigin-RevId: 578491484
(cherry picked from commit d42c23706b615d1987f988fe219ab0fe61d44ac6)

* Split media1/media3 conversion methods out of `MediaUtils`

Android Studio removed some nested imports, but I think the extra
qualification at the usage site is actually mostly helpful, so I'm
leaving it as-is.

PiperOrigin-RevId: 578518880
(cherry picked from commit 72b7019578f3051e1bec826cf0ac401a86d818dc)

* Fix access to stale ByteBuffer in FfmpegAudioDecoder

The native code can now reallocate the buffer if it needs to grow
its size, so we have to reacquire a reference in the Java code to
avoid accessing a stale instance.

This fixes a bug introduced by https://github.com/androidx/media/pull/746/commits/8750ed8de6469dc818007f2eb254df9ddbd52cc5.

PiperOrigin-RevId: 578799862
(cherry picked from commit ae6f83d298424bd405372803bb8b206fc95a2d0f)

* Fix proguard rule to also keep referenced class name

PiperOrigin-RevId: 579234050
(cherry picked from commit bce82bdc752a8da1d7c1f78bdfb417414407849b)

* Remove old pre-releases from the github bug template

PiperOrigin-RevId: 580554963
(cherry picked from commit 508582d56c9f8e6219d2e93f0f80ea180b4ad272)

* Don't crash when receiving a bad playback state

PiperOrigin-RevId: 580942377
(cherry picked from commit e79809616cd0ecb6f39cbeffdaaf143c260f64e6)

* Parse "f800" as channel count of 5 for Dolby in DASH manifest

Issue: androidx/media#688
PiperOrigin-RevId: 581908905
(cherry picked from commit 79711ebd3f8626d9ec31f7ac18434625caeac28f)

* Expand frame drop workaround to Realme C11

Based on on-device testing, this device seems to have the same issue as Moto G (20) where frames are dropped despite configuring the decoder not to drop frames.

PiperOrigin-RevId: 581943805
(cherry picked from commit 330713f687d4ebaec9ee8e9aaf39db503f299ce3)

* Update recommended way to suppress `@UnstableApi` errors in `lint.xml`

#minor-release

PiperOrigin-RevId: 582599098
(cherry picked from commit bd7615c0b83df8187daaf7e8d91eb1ce9bb35240)

* Workaround layout problems with Material Design

In some contexts (e.g. BottomSheetDialogFrament), Material Design
themes will override the default of singleLine=false to true. This
causes layout problems because the forward/rewind buttons are no
longer visible with singleLine=true.

This problem can be avoided by explicitly requesting the default
value of false in our layout files.

Issue: androidx/media#511

#minor-release

PiperOrigin-RevId: 582604131
(cherry picked from commit 310e2edccac75b1ed30eb69520224cb48d1cc190)

* Populate `MediaMetadata.extras` to `MediaMetadataCompat`

Ensures backward compatibility.

Issue: androidx/media#802
PiperOrigin-RevId: 583425114
(cherry picked from commit 6df240877c30aedb271c2bc74c54fc2bab0e4cbf)

* Use `.test` top level domain for test URI

PiperOrigin-RevId: 583951327
(cherry picked from commit ffbaa090aa24ef138d38b16b9e6e45560b5c8dd3)

* Return empty timeline when media info is null

Issue: androidx/media#708
PiperOrigin-RevId: 584054624
(cherry picked from commit 167f50a9ca8b8cbd80bc5ff4c7afd4c6a1db7dc2)

* Add test case to test position conversion when POSITION_UNKNOWN

PiperOrigin-RevId: 584261559
(cherry picked from commit ec478138baf58ed5c1a4c5117d5f28e5b40c94eb)

* Avoid clipping live offset override to min/max offsets

The live offset override is used to replace the media-defined
live offset after user seeks to ensure the live adjustment adjusts
to the new user-provided live offset and doesn't go back to the
original one.

However, the code currently clips the override to the min/max
live offsets defined in LiveConfiguration. This is useful to
clip the default value (in case of inconsistent values in the media),
but the clipping shouldn't be applied to user overrides as
the player will then adjust the position back to the min/max
and doesn't stay at the desired user position.

See https://github.com/androidx/media/commit/2416d9985718accfcc00ddc951afa217c261f7ae#r132871601

PiperOrigin-RevId: 584311004
(cherry picked from commit af0282b9db62a8c5de1dbcc49794872d0157c1ab)

* MidiExtractor: mark only the first sample as key-frame

This change fixes a bug with seeking forward in MIDI. When seeking forward,
the progressive media period attempts to seek within the sample queue, if a
key-frame exists before the seeking position. With MIDI, however, we can
only skip Note-On and Note-Off samples and all other samples must be sent
to the MIDI decoder.

When seeking outside the sample queue, the MidiExtractor already
instructs the player to start from the beginning of the MIDI input. With
this change, only the first output sample is a key-frame, thus the
progressive media period can no longer seek within the sample queue and
is forced to seek from the MIDI input start always.

Issue: androidx/media#704

PiperOrigin-RevId: 584321443
(cherry picked from commit ec08db458e6cedcb79a42f10eaac7f8da7e7bcdb)

* Add session extras to the state of the controller

This change adds `MediaController.getSessionExtras()` through
which a controller can access the session extras.

The session extras can be set for the entire session when
building the session. This can be overridden for specific
controllers in `MediaSession.Callback.onConnect`.

PiperOrigin-RevId: 584430419
(cherry picked from commit a063d137b4307348a140ec6a2b6d254db294395e)

* Merge pull request #707 from equeim:ffmpeg-6.0

PiperOrigin-RevId: 584893190
(cherry picked from commit 45b51d8c972f957e02097c5ecff2261ffe23e397)

* Remove redundant ) in Javadoc

PiperOrigin-RevId: 584910697
(cherry picked from commit 85a54e2e190b705367b0d2dd4d7fcd71900b3fdd)

* Fix typo in `DashManifestParser`

PiperOrigin-RevId: 585017285
(cherry picked from commit 479344d74e1e63d83cd94ed14517e27030c85e6a)

* Avoid value close to overflow for `KEY_OPERATING_RATE`

Using `Integer.MAX_VALUE` risks causing arithmetic overflow in the codec
implementation.

Issue: androidx/media#810

PiperOrigin-RevId: 585104621
(cherry picked from commit ad40db448943fef579879c9c2a988f514b254109)

* Work around codec frame rate issues in Redmi Note 9 Pro

The decoder and encoder won't accept high values for frame rate, so avoid
setting the key when configuring the decoder, and set a default value for the
encoder (where the key is required).

Also skip SSIM calculation for 4k, where the device lacks concurrent decoding
support.

PiperOrigin-RevId: 585604976
(cherry picked from commit 8b38b34b9f02c3648d2988c4cdaca005fbf8f1cd)

* Restrict operating rate workaround to SM8550

PiperOrigin-RevId: 585613041
(cherry picked from commit e84a13fb54ab0d325b928bf7ec0d8632ccbc8ca3)

* Merge pull request #837 from superjohan:fix/android-14-clearkey

PiperOrigin-RevId: 585639025
(cherry picked from commit 5f27b1821027d4cd086b87242e9e756a301b8e9a)

* Update emulator device names

PiperOrigin-RevId: 585682881
(cherry picked from commit b598c96c2f604af731d43e5bd021e5198dab0af1)

* Exit early progressive loads if the load task is canceled

Add an check when loading progressive media in case the load
is canceled. If the player is released very early, the progressive
media period may carry on with the initial loading unnecessarily.

PiperOrigin-RevId: 586288385
(cherry picked from commit 3d1d8f4439f194029d1522137b7f428e96bf61b3)

* Don't include null text or bitmaps in `Cue.toBundle()`

`fromBundle` doesn't distinguish between `FIELD_BITMAP` and `FIELD_TEXT`
being present with a null value, or being absent, so we might as well
avoid including them when the value is null.

I've separated this from a later change to add
`Cue.toSerializableBundle` which will also skip setting a bitmap value
into the `Bundle` if `this.bitmap == null`. This is partly because it
results in changes to a lot of extractor test dump files, and it's
easier to review that as a separate change.

PiperOrigin-RevId: 586626141
(cherry picked from commit 28c210686f54d52610fe2f9560ad1dfa73753ccd)

* MCR: Ensure `mediaCrypto` and `codec` are atomically non-null

`mediaCrypto` is initialized before `codec` in
`maybeInitCodecOrBypass`. Before this change, it was possible for
`maybeInitCodecOrBypass` to complete with `mediaCrypto != null` and
`codec == null`, in particular if it was run as part of clearing the
player surface (since in that case, no video codec is initialized).
This inconsistent state then causes issues during a later invocation of
`maybeInitCodecOrBypass`, when `mediaCrypto` is still non-null, and
`mediaCryptoRequiresSecureDecoder = true`, but the
content has been changed to unencrypted with no associated DRM session.
This results in a playback error, because a secure decoder is
initialized but there's no DRM session available to work with it.

This change ensures that when `maybeInitCodecOrBypass` completes,
either both `mediaCrypto != null` and `codec != null` (i.e. codec
initialization was completed) or `mediaCrypto == null` and
`codec == null` (i.e. codec initialization was not completed). We also
ensure that when nulling out `mediaCrypto` we also set
`maybeInitCodecOrBypass = false`. A later change should be able to
demote `maybeInitCodecOrBypass` from a field to a local in order to
remove any risk of that part of state becoming out of sync. This
resolves the issue, because during the second invocation of
`maybeInitCodecOrBypass` an insecure decoder is now (correctly)
initialized and the unencrypted content is successfully played.

#minor-release

PiperOrigin-RevId: 587713911
(cherry picked from commit 913f6da08305b36798c84d5134d19b2d11affdd2)

* Map VORBIS channel layout to Android layout

Both the extension OPUS decoder and the OMX/C2 MediaCodec
implementations for OPUS and VORBIS decode into the channel
layout defined by VORBIS. See
https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-140001.2.3

While this is technically correct for a stand-alone OPUS or VORBIS
decoder, it doesn't match the channel layout expected by Android.
See https://developer.android.com/reference/android/media/AudioFormat#channelMask

The fix is to apply the channel mapping after decoding if needed.
Also add e2e tests with audio dumps for the extension renderer,
including a new 5.1 channel test file.

Issue: google/ExoPlayer#8396

PiperOrigin-RevId: 588004832
(cherry picked from commit b1541b096f9dc4d1f9ca71b6743c836f6bd4de89)

* Limit processing Opus decode-only frames by seek-preroll in offload

As Opus decoders skip some bytes prior to playback during a seek, the renderer for bypass playback should send samples to the decoder even if they would be decode-only. However, the renderer should not send samples with time preceding that range. This change adds that constraint.

#minor-release

PiperOrigin-RevId: 588014983
(cherry picked from commit d1e38abf93353af1bc3fb2d9a0dfbac01e387f3e)

* Fix nullability issue in MediaControllerImplLegacy

PiperOrigin-RevId: 588035411
(cherry picked from commit e0f1783a54867ee81d6f9fb93ffdcee8451f2118)

* Add Robolectric e2e test support for HEVC content

PiperOrigin-RevId: 588055594
(cherry picked from commit d4fe3fe318ef5961911b828aa7a42b124acfc186)

* Add extractor and playback tests for Pixel JPEG motion photo…
@androidx androidx locked and limited conversation to collaborators Mar 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests