124 Commits

Author SHA1 Message Date
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
tonihei
2fd4aac310 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
2022-11-22 10:08:08 +00:00
tianyifeng
4ce171a3cf 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
2022-11-22 09:53:40 +00:00
tonihei
1143edc59a Rename getVideoSurfaceSize to getSurfaceSize
This better matches the callback name (onSurfaceSizeChanged) and
probably cause less confusion with getVideoSize.

PiperOrigin-RevId: 488669786
2022-11-16 12:15:05 +00:00
tonihei
33bea391d4 Ensure listener invocations use final state variable.
The MediaControllerImplBase listener invocations currently use the
class member state that can change if one of the listener method
implementations changes the state recursively.

Updating the listener invocations to use a final local variable
ensures all listeners get consistent updates.

PiperOrigin-RevId: 487503373
2022-11-10 15:00:07 +00:00
tonihei
c6a0ba25f9 Split test methods more clearly in arrange, act, assert.
The tests in MediaControllerCompatCallbackWithMediaSessionTest
don't follow this pattern very consistently at the moment.

PiperOrigin-RevId: 487501913
2022-11-10 14:59:07 +00:00
tonihei
c5e071e556 Align PlaybackStateCompat states with logic in MediaSessionConnector
Creating the PlaybackStateCompat from a media3 Player state is done
already by the MediaSessionConnector (and used widely). The media3
session module should set the same states under the same circumstances
to ensure compatiblity and consistency.

PlaybackStateCompat changes made in media3 session:
 - Use STATE_STOPPED when player is ended instead of STATE_PAUSED
 - Use STATE_PLAYING when playback is suppressed temporarily.
 - Set the playback speed to 0 if the player is not playing.
 - Add extras for mediaId and user-set playback speed.

Part of the problem was that Player.isPlaying() was used to check
the state. Unfortunately, MockPlayer.isPlaying() is implemented in
a way that makes it hard to test these changes, because the value
is set independently of playbackState, playWhenReady and suppression
reason. To be able to write consistent, logical tests, this change
also removes the independent setting of isPlaying in MockPlayer to
align it better with a real player. This requires to update some
other tests to use alternative methods.

PiperOrigin-RevId: 487500859
2022-11-10 14:58:06 +00:00
tonihei
0b4ba3e3a6 Wait with PlayerInfo updates until all pending operations are done
Accepting a PlayerInfo while the MediaController is masking its state
means we are reverting all masking changes we've made earlier. This
only makes sense if the update already contains the masked operation.
If multiple operations are in flight (or are sent from the session
while they are in flight), we need to wait until all of them are
handled before accepting new updates.

In cases where a new update from the session excludes the Timeline
and the masked state is incompatible with the new update, we also
risk an exception if we accept the update too early.

PiperOrigin-RevId: 487266899
2022-11-10 14:38:56 +00:00
christosts
c403b4ce7c MediaController: Add missing event flags (2/2)
This is the follow-up commit where the onEvents callback
raised by MediaController contains the missing events, for the
case where MediaController is connected to a legacy MediaSession.

#minor-release

PiperOrigin-RevId: 487231996
2022-11-10 14:36:50 +00:00
christosts
09651ed2e3 MediaControllerListenerWithMediaSessionCompatTest: clean imports
Remove static imports to Player constants to make the code more readable.

#minor-release

PiperOrigin-RevId: 486619911
2022-11-08 11:31:04 +00:00
michaelkatz
9336b95bf4 Changed MediaController to return last estimated position while paused
The method getCurrentPosition() may return a lesser position during pause than the previous retrieved value due to ipc call delay in playerInfo update. Users see track position jump backwards at pause. Fixed to return last estimated position while paused if have not received updated playerInfo. Code is deduped to point getContentPosition() to getCurrentPosition() when !isPlayingAd.

PiperOrigin-RevId: 486617341
2022-11-08 11:30:01 +00:00
Googler
4271056545 Add 'Player.getVideoSurfaceSize' that returns the size of the surface
on which the video is rendered.

Design Doc: go/aaos-mu-media-dd

PiperOrigin-RevId: 485884772
2022-11-08 11:25:43 +00:00
tianyifeng
77fedd8d7d Load bitmaps for MediaMetadataCompat and handle the metadata updates.
* Add `Listener` in `MediaSession` with method `onNotificationRefreshRequired(MediaSession)`.
* Add `MediaSessionService` as the listener of the `MediaSession` when `MediaSession` is added to `MediaSessionService`
* Load bitmap when update metadata in `MediaSessionLegacyStub` and call `onNotificationRefreshRequired` when bitmap asynchronously arrives.

PiperOrigin-RevId: 485376145
2022-11-08 11:19:04 +00:00
bachinger
4c9ca8fad1 Set BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED automatically
This root extra needs to be set by apps manually in media1 and we
can do that automatically in Media3 based on the available session
commands.

#minor-release

PiperOrigin-RevId: 484286833
2022-10-31 11:44:57 +00:00
bachinger
21022c77be Use MediaBrowserCompat.rootHints as connections hints
In Media3 there is the useful concept of connection hints that a
client can set when building the session and that are sent to the
service and passed to the `Callback.onConnect()` method when the
browser connects.

These connection hints are then included in the `ControllerInfo`
object that later will be passed to every callback method and the
implementor can then take decisions specific to these connection
hints.

These connection hints are not available in media1. However, when
an app creates a `MediaBrowserCompat` object, the constructor takes
a rootHint object that is sent to
`MediaBrowserServiceCompat.onGetRoot()`.

This change uses the browser rootHints as the connection hints when
creating the `ControllerInfo` for legacy browsers and makes them
available to the `MediaLibrarySession.Callback` domain methods in
the same way as connection hints of a Media3 browser.

PiperOrigin-RevId: 484220748
2022-10-31 11:43:21 +00:00
christosts
46d5a0e33b MediaController: Add missing event flags (1/2)
This is the first commit out of two. This change adds the missing event
flags for the onEvents() callback when MediaController is connected to a
media3 session (see MediaControllerImplBase). I updated the
MediaControllerListenerTest and MediaControllerStateMaskingTest with
assertions that on onEvents() is called alongside individual
Player.Listener callbacks.

There will be a follow-up change for the case where a MediaController is
connected to a legacy MediaSession (MediaControllerImplLegacy). I've
split this in two separate changes to make the size of the commit
manageable for reviewing.

#minor-release

PiperOrigin-RevId: 481933437
2022-10-24 10:34:30 +00:00