References to the service are kept from MediaSessionStub
and from a long-delayed Handler messages in ConnectionTimeoutHandler.
Remove strong references from these places by making the timeout
handler static and ensuring ConnectedControllersManager only keeps
a weak reference to the service (as it's part of MediaSessionStub).
Issue: androidx/media#346
PiperOrigin-RevId: 527543396
(cherry picked from commit 8c262d6c072304ed9f16feca64b70a18645cc908)
To reliably reject the System UI playback resumption notification on
all API levels (specifically API 30), the backward compatibility layer
needs to return `null` for the library root.
This is not possible in the Media3 implementation. This change allows
an app to return a `LibraryResult.ofError(RESULT_ERROR_NOT_SUPPORTED)`
that then is translated to return null by the backwards compatibility
layer.
Issue: androidx/media#355
Issue: androidx/media#167
Issue: androidx/media#27
See https://developer.android.com/guide/topics/media/media-controls#mediabrowserservice_implementation
PiperOrigin-RevId: 527276529
(cherry picked from commit 7938978b5165a9cbb63a6ee1fe5209934e996c6e)
And remove unnecessary check for isDone.
Issue: androidx/media#345
PiperOrigin-RevId: 525999615
(cherry picked from commit 186f3d5c7767e65cc823846b045282c05ed30da5)
This is a bug currently, where commands are created once but never
updated again if the actions in MediaSessionCompat are changed.
PiperOrigin-RevId: 525999084
(cherry picked from commit 79fab6783e07ea594410be347c8a3d6e1124707d)
The sessions may have different application threads for their players,
and the service with its notification provider runs on the main thread.
To ensure everything runs on the correct thread, this change labels
methods where needed and fixes thread access in some places.
Issue: androidx/media#318
PiperOrigin-RevId: 524849598
(cherry picked from commit ffa3743069408cf794cd48e8608df749e09d719e)
This check was a leftover from when the metadata was generated from
the MediaItem only. Since we moved to the actual MediaMetadata fields,
the check is completely unnecessary and prevents accessing metadata
when the GET_CURRENT_MEDIA_ITEM command is not available.
PiperOrigin-RevId: 524837587
(cherry picked from commit e0bb23d4634421ede8827948a3ddae9c5d4a9089)
The overrides specified by a MediaController may not use the exact
same TrackGroup instances as known to the Player because the groups
have been bundled to and from the controller. This bundling may
alter the instance slightly depending on the version used on each
side of the communication and the fields set (e.g. Format.metadata
is not supported for bundling).
This issue can be solved by creating unique track group ids for
each group on the session side before bundling. On the way back,
the groups in the track selection parameters can be mapped backed
to their original instances based on this id.
Issue: androidx/media#296
PiperOrigin-RevId: 523986626
(cherry picked from commit 1c557e2fd18c77243474af2f8c99fa6ea061b38a)
This change selects the best suited media button receiver
component and pending intent when creating the legacy
session. This is important to ensure that a service can
be started with a media button event from BT headsets
after the app has been terminated.
The `MediaSessionLegacyStub` selects the best suited
receiver to be passed to the `MediaSessionCompat`
constructor.
1. When the app has declared a broadcast receiver for
`ACTION_MEDIA_BUTTON` in the manifest, this broadcast
receiver is used.
2. When the session is housed in a service, the service
component is used as a fallback.
3. As a last resort a receiver is created at runtime.
When the `MediaSessionLegacyStub` is released, the media
button receiver is removed unless the app has provided a
media button receiver in the manifest. In this case we
assume the app supports resuming when the BT play intent
arrives at `MediaSessionService.onStartCommand`.
Issue: androidx/media#167
Issue: androidx/media#27
Issue: androidx/media#314
PiperOrigin-RevId: 523638051
(cherry picked from commit e54a9343980c7f6c44ddf0edbb938dd5f6b11193)
And also mention a few restrictions regarding legacy components
in Javadoc.
Issue: androidx/media#293
PiperOrigin-RevId: 522005562
(cherry picked from commit 502969a42b2ba07ada555a38841c7c65baeaa594)
MediaItems are not meant to be unique in a playlist. If a legacy
session publishes multiple items that get converted to equal MediaItems,
the current code fails because we look up queue ids in a Map (that
doesn't allow duplicate entries).
Fix this by storing a simple list of items with additional data.
Issue: androidx/media#290
PiperOrigin-RevId: 521993802
(cherry picked from commit 219967c5a3ff8d8957a07e39c04ea27b657cab92)
The check currently relies on the default value of 0 returned if the
Bundle doesn't define a pid. But in some cases, like Robolectric unit tests,
0 is a possible pid. The check can be improved by directly asserting that
the value is defined.
PiperOrigin-RevId: 521414649
(cherry picked from commit 694d690bc03a34e112afc6cca58eb2761a25402a)
Custom commands from controller to session are blocked if they are
not listed in the available session command list. This isn't well
documented in the Javadoc currently.
#minor-release
PiperOrigin-RevId: 514733568
(cherry picked from commit 20669fca275554698c9176250005055b230485b3)
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)
The current javadoc refers to the SessionCallback#onConnected, which doesn't exist.
PiperOrigin-RevId: 510261965
(cherry picked from commit fc642eb45f6c997a2a501bcc3ea19043cd9911eb)
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)
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)
This allows a MediaController to understand which methods calls
are available on a legacy session.
PiperOrigin-RevId: 504306806
(cherry picked from commit 067340cb0a03dede0f51425de00643fe3789baf2)
Created unified MediaUtils method to handle various logic for calling Player.setMediaItems from MediaSessionStub and MediaSessionLegacyStub
PiperOrigin-RevId: 504271877
(cherry picked from commit 7fbdbeb6cafe075f04b6a4321ef826643b3482e1)
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)
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)
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)
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)
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)
PlayerWrapper advertises PlaybackStateCompat actions to the legacy
MediaSession based on the player's available commands.
PiperOrigin-RevId: 502559162
(cherry picked from commit 39f4a17ad4ac3863af22e12711247c7a87b8613e)
This player didn't fully check all player commands before calling the
respective methods.
PiperOrigin-RevId: 502353704
(cherry picked from commit a2a44cdc02abadd473e26e1fd9f973210d4c5f0e)
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)
This avoids throwing exceptions for correct (but deprecated) Player
method invocations.
PiperOrigin-RevId: 502341428
(cherry picked from commit 86a95c2a4afd861986376f9dc31e0d65910e6e74)
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)
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)
Also clean up the strict mode violations of using `BitmapFactory.convertToByteArray` on the main thread.
PiperOrigin-RevId: 496422355
(cherry picked from commit d848d3358a67ce2439db7cf170eec7b8c3ecffbf)
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)
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)
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)
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 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)
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)
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)