139 Commits

Author SHA1 Message Date
tonihei
2c07468908 Implement Player.replaceMediaItem(s)
This change moves the default logic into the actual Player
implementations, but does not introduce any behavior changes compared
to addMediaItems+removeMediaItems except to make the updates "atomic"
in ExoPlayerImpl, SimpleBasePlayer and MediaController. It also
provides backwards compatbility for cases where Players don't support
the operation.

Issue: google/ExoPlayer#8046

#minor-release

PiperOrigin-RevId: 534945089
2023-05-25 10:00:02 +01:00
tonihei
33af245465 Improve handling of adding items to empty playlist in MediaController
This is a follow-up to 99dac0be0f where we made the same change in
ExoPlayerImpl and SimpleBasePlayer, but for consistency it makes
sense to also update the masking code in MediaControllerImplBase to
assume the same logic.

Note: MediaControllerImplLegacy already handles this case via
setMediaItems and doesn't need to be updated further.

#minor-release

PiperOrigin-RevId: 534038759
2023-05-24 15:40:42 +01:00
tonihei
caf1c77af1 Keep pending initial position when setting empty playlist
MediaControllerImplBase currently drops the pending initial seek
position when a user sets an empty playlist.

When seeking in empty playlists and setting new empty playlists,
the class also drops the the period index (and wrongly assigns zero
instead of the windowIndex).

#minor-release

PiperOrigin-RevId: 534035046
2023-05-24 15:38:17 +01:00
bachinger
2a6f893fba Set video size to 0/0 when video render is disabled
In terms of MCVR with a `VideoRendererEventListener`, the video size is set to
0/0 right after `onVideoDisabled()` is called and is set to the actual size as
soon as the video size is known after 'onVideoEnabled()`.

For ExoPlayer and in terms of the `Player` interface, `Player.getVideoSize()`
returns a video size of 0/0 when `Player.getCurrentTracks()` does not support
`C.TRACK_TYPE_VIDEO`. This is ensured by the masking behavior of
`ExoPlayerImpl` that sets an empty track selection result when the playing
period changes due to a seek or timeline removal.

When transitioning playback from a video media item to the next, or when
seeking within the same video media item, the renderer is not disabled.

#minor-release

PiperOrigin-RevId: 533479600
2023-05-24 15:28:20 +01:00
bachinger
3fa666c687 Return full media item when SystemUI calls service on device boot time
#minor-release

PiperOrigin-RevId: 533465595
2023-05-19 17:23:22 +01:00
ibaker
b3db85133a Add android.namespace to all build.gradle files
This is a pre-requisite for the Android Studio upgrade assistant to
upgrade from AGP 7.2.2 to 8.0.1, otherwise it fails and complains
this is missing.

Issue: androidx/media#409
PiperOrigin-RevId: 533463246
2023-05-19 17:19:15 +01:00
tonihei
96dd0ae583 Add consistency check to sending and receiving position updates
The periodic updates are only meant to happen while we are in the
same period or ad. This was already guaranteed except for two cases:
1. The Player in a session has updated its state without yet calling
   its listeners
2. The session scheduled a PlayerInfo update that hasn't been sent yet

... and in both cases, the following happened:
 - The change updated the mediaItemIndex to an index that didn't exist
   in a previous Timeline known to the Controller
 - One of the period position updates happened to be sent at exactly
   this time

This problem can be avoided by only scheduling the update if we are
still in the same period/ad and haven't scheduled a normal PlayerInfo
update already.

Since new MediaControllers may still connect to old sessons with this
bug, we need an equivalent change on the controller side to ignore such
buggy updates.

PiperOrigin-RevId: 532089328
2023-05-16 09:48:50 +01:00
bachinger
9bf6b7ea20 Implement SystemUI contract for media resumption
When a `MediaButtonReceiver` is found in the manifest, the library
can implement the contract of SystemUI to signal that the app wants
a playback resumption notification to be displayed.

And, vice versa, if no `MediaButtonReceiver` is in the manifest, the
library will signal to not show the notification after the app has been
terminated.

#minor-release

PiperOrigin-RevId: 531516023
2023-05-15 10:38:44 +01:00
bachinger
5e4421c2ba Add MediaSession.setSessionActivity(PendingIntent)
The session activity is already sent to the controller with the
`ConnectionState` when it connects. This change adds the ability to update the
activity.

This allows an app to change the intent that is used to open an activity
for the notification. An app is likely to want to change the session activity
just before the session is released. This allows to use a different activity or
more importantly the back stack of the activity for while the app is running
and when used for the playback resumption notification.

PiperOrigin-RevId: 530627102
2023-05-11 09:52:04 +00:00
bachinger
e48dec5f2c Add MediaButtonReceiver for Media3
The media button has API support with
`Callback.getPlaybackResumption()` that apps need to override to provide
a playlist to resume playback with.

Issue: androidx/media#167
PiperOrigin-RevId: 529495845
2023-05-05 16:42:44 +00:00
bachinger
eac26b1838 Fix type annotation of MockPlayer.notifyPlayWhenReadyChanged
PiperOrigin-RevId: 529030412
2023-05-03 17:13:19 +01:00
tonihei
3693ca4bbb Add MediaSession.getControllerForCurrentRequest
This is a helper method that can used to obtain information about
the controller that is currently calling a Player method.

PiperOrigin-RevId: 527268994
2023-04-27 12:21:19 +01:00
tonihei
0bac4e24e4 Add routing controller id to DeviceInfo
And forward the id to the VolumeProviderCompat and read it from the platform
MediaController for compatibility.

PiperOrigin-RevId: 526046892
2023-04-24 11:35:08 +01:00
tonihei
d9fd8f4310 Add Builder for DeviceInfo
This simplifies the addition of new fields in the future.

Also do some misc clean up for the volume limit values:
 - Add some documentation to mention assumed defaults
 - Add the IntRange annotations to match the ones we have in Player
   already
 - Mention the limits in the relevant Player methods
 - Avoid bundling default values
 - Improve range checks for masking in MediaController

PiperOrigin-RevId: 526029619
2023-04-24 11:33:13 +01:00
tonihei
79fab6783e Update available commands when MediaSessionCompat actions change
This is a bug currently, where commands are created once but never
updated again if the actions in MediaSessionCompat are changed.

PiperOrigin-RevId: 525999084
2023-04-24 11:31:15 +01:00
tonihei
e0bb23d463 Remove unnecessary check for currentMediaItem in legacy session stub
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.

#minor-release

PiperOrigin-RevId: 524837587
2023-04-17 17:18:57 +01:00
tonihei
1c557e2fd1 Ensure TrackSelectionParameters overrides match existing groups
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.

#minor-release

Issue: androidx/media#296
PiperOrigin-RevId: 523986626
2023-04-13 16:30:45 +01:00
jbibik
c71e4bf1ff Extend Player interface, overloading 4 device-volume methods with flags
Previously, ExoPlayerImpl had volume flags hardcoded to SHOW_UI, but now the developer can choose what happens on volume change. The old methods have been deprecated.

PiperOrigin-RevId: 523974358
2023-04-13 16:30:30 +01:00
tonihei
c5baf2388c Rename misleading COMMAND_GET/SET_MEDIA_ITEMS_METADATA
The setter command is only used for setPlaylistMetadata and can
be named COMMAND_SET_PLAYLIST_METADATA. The getter commnad is
used to access getMediaMetadata and getPlaylistMetadata and can
be better named COMMAND_GET_METADATA to reflect this usage.

PiperOrigin-RevId: 523673286
2023-04-12 16:59:38 +01:00
tonihei
ae875648a7 Update available commands when setting a new player in MediaSession
#minor-release

PiperOrigin-RevId: 523633865
2023-04-12 16:55:47 +01:00
tonihei
5b1370e686 Set duration in QueueTimeline
If the duration is reported in MediaMetadataCompat, it should
also be set in the QueueTimeline to match controller.getDuration()

PiperOrigin-RevId: 522022953
2023-04-05 13:17:58 +01:00
tonihei
502969a42b Implement missing broadcastCustomCommand to legacy controller
And also mention a few restrictions regarding legacy components
in Javadoc.

#minor-release

Issue: androidx/media#293
PiperOrigin-RevId: 522005562
2023-04-05 11:30:55 +01:00
tonihei
219967c5a3 Allow duplicated MediaItems in a legacy session
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.

#minor-release

Issue: androidx/media#290
PiperOrigin-RevId: 521993802
2023-04-05 15:49:43 +01:00
tonihei
b3788ce568 Remove deprecated stop(boolean)
This method has been deprecated for over 2 years.

PiperOrigin-RevId: 520586238
2023-03-30 17:24:35 +00:00
tonihei
fc54a7a487 Add COMMAND_RELEASE to set whether Player instances can be released
This wasn't added so far because releasing is always allowed from a
MediaController (as it just releases the connection, not the session
player). But Player instances can be created for other purposes and
the receiver of a Player instance should not always be allowed to
call release if it doesn't own the player resource.

PiperOrigin-RevId: 519121122
2023-03-30 17:09:28 +00:00
ibaker
c0459e6ae1 Exclude test_session_{common,current} from API and Javadoc tests
We don't publish documentation for these, nor maven artifacts for them -
they only exist as source code on GitHub.

PiperOrigin-RevId: 513863141
2023-03-07 11:48:38 +00:00
christosts
ebe7ece1eb 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
2023-02-02 15:38:04 +00:00
bachinger
4a9cf7d069 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
2023-02-01 10:34:25 +00:00
bachinger
5c82d6bc18 Double tap detection for Bluetooth media button events only
Issue: androidx/media#233
#minor-release
PiperOrigin-RevId: 505078751
2023-02-01 10:24:01 +00:00
tonihei
067340cb0a 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
2023-01-25 18:42:51 +00:00
michaelkatz
bb11e0286e 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
2023-01-23 12:34:44 +00:00
tonihei
e961c1b5e9 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
2023-01-23 12:28:09 +00:00
tonihei
f15b752543 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
2023-01-23 12:25:48 +00:00
christosts
39f4a17ad4 Filter what PlaybackStateCompat actions are advertised
PlayerWrapper advertises PlaybackStateCompat actions to the legacy
MediaSession based on the player's available commands.

PiperOrigin-RevId: 502559162
2023-01-18 11:58:10 +00:00
tonihei
cfcce9aec9 Fix command check in MediaControllerImplBase
The command check for setDeviceMuted was wrong.

PiperOrigin-RevId: 502355332
2023-01-17 02:08:47 +00:00
tonihei
a2a44cdc02 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
2023-01-17 02:08:00 +00:00
tofunmi
a9135e2eff Move BitmapLoader to common.
The migration strategy is to deprecate `androidx.media3.session.BitmapLoader` and copy the file into common since BitmapLoader is a public interface that apps could be relying on.

PiperOrigin-RevId: 501266521
2023-01-17 01:50:18 +00:00
bachinger
375299bf36 Use onMediaMetadataChanged for updating the legacy session
Issue: androidx/media#219
PiperOrigin-RevId: 501080612
2023-01-17 01:46:39 +00:00
tianyifeng
d848d3358a Add BitmapLoader injection in MediaController
Also clean up the strict mode violations of using `BitmapFactory.convertToByteArray` on the main thread.

PiperOrigin-RevId: 496422355
2022-12-21 15:23:38 +00:00
tonihei
0749b05923 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
2022-12-21 15:11:28 +00:00
tonihei
a1954f7e0a 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
2022-12-21 15:07:20 +00:00
tonihei
927b2d6a43 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
2022-12-12 11:38:06 +00:00
tonihei
ae8000aeca 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
2022-12-12 11:32:57 +00:00
tonihei
ca4c6efdb7 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
2022-12-12 11:02:38 +00:00
christosts
2424ee7792 Misc fix in gradle build file
Issue: androidx/media#209

#minor-release

PiperOrigin-RevId: 490492223
2022-11-24 14:46:43 +00:00
bachinger
3d8c52f28d 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
2022-11-24 14:45:37 +00:00
bachinger
68908be18d 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
2022-11-24 14:43:44 +00:00
tonihei
03f0b53cf8 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
2022-11-24 14:39:54 +00:00
bachinger
1803d1cdb8 Migrate BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS to Media3
PiperOrigin-RevId: 490376734
2022-11-24 14:38:41 +00:00
tianyifeng
8ce1213ddd 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
2022-11-24 14:37:23 +00:00