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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
Also clean up the strict mode violations of using `BitmapFactory.convertToByteArray` on the main thread.
PiperOrigin-RevId: 496422355
(cherry picked from commit d848d3358a67ce2439db7cf170eec7b8c3ecffbf)
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)
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)
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)
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)
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)
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)
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)
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)
This improves the time taken to construct PlayerInfo from bundle from ~600ms to ~450ms.
PiperOrigin-RevId: 495055355
(cherry picked from commit 395cf4debc52c9209377ea85a319d2e27c6533ce)
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)
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)
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)
It looks like this was added accidentally in <unknown commit>.
PiperOrigin-RevId: 493834134
(cherry picked from commit 533f5288f4aec47a75357bf308907d1686ba493a)
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)
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)
Fix some other link titles and destinations spotted along the way.
#minor-release
PiperOrigin-RevId: 493276172
(cherry picked from commit 636a4a8538ccfb235eeca7d9131d4b5d4d95e9aa)
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)
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)
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)
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)
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)
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)