87 Commits

Author SHA1 Message Date
tonihei
8cc37db8e5 Rename getVideoSurfaceSize to getSurfaceSize
This better matches the callback name (onSurfaceSizeChanged) and
probably cause less confusion with getVideoSize.

PiperOrigin-RevId: 488669786
(cherry picked from commit 1143edc59ac96ec8524e8203d9445dbb0f006630)
2022-11-17 10:06:29 +00:00
tonihei
7f17ff6d00 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
(cherry picked from commit 33bea391d42cb5669e6d2c97c0553f3c0c63467b)
2022-11-10 12:56:11 +00:00
tonihei
a9eb121169 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
(cherry picked from commit c6a0ba25f996b77adf6bf0dd9921f429d5950437)
2022-11-10 12:47:12 +00:00
tonihei
58d670d941 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
(cherry picked from commit c5e071e556931331cc780fda5177d556d51ff3da)
2022-11-10 12:40:37 +00:00
tonihei
dddc6026e9 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
(cherry picked from commit 0b4ba3e3a6130253b801ddc231501168efce8901)
2022-11-09 17:29:31 +00:00
christosts
707c2d894d 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
(cherry picked from commit c403b4ce7ce9a2964ff754bb394782cc36fb882d)
2022-11-09 14:58:49 +00:00
christosts
3bad1f326d MediaControllerListenerWithMediaSessionCompatTest: clean imports
Remove static imports to Player constants to make the code more readable.

#minor-release

PiperOrigin-RevId: 486619911
(cherry picked from commit 09651ed2e3134b87ea832ba05f7bdd2d11289bd6)
2022-11-07 11:55:08 +00:00
michaelkatz
8270dd4536 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
(cherry picked from commit 9336b95bf4355c4b1e43f95879d9af45cf90cd19)
2022-11-07 11:36:36 +00:00
Googler
b780635c0b 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-03 15:50:19 +00:00
tianyifeng
f5afec955a 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
(cherry picked from commit 77fedd8d7d511ff97b0441aa9136d0f1aaecef4b)
2022-11-01 18:43:26 +00:00
bachinger
dddb4841af 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
(cherry picked from commit 4c9ca8fad1c4d4c475a0baee243c099204bc23af)
2022-10-27 17:20:06 +00:00
bachinger
1c81587398 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
(cherry picked from commit 21022c77be44fefeaa25ef9fb72be7d48e51a0bc)
2022-10-27 11:50:03 +00:00
christosts
ba84c2a09c 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
(cherry picked from commit 46d5a0e33bd562cd9e6420b342a68bf112847f83)
2022-10-18 15:54:54 +00:00
bachinger
fc1089f68a Migrate media constants from androidx.media.util.MediaConstants
Adds root extras and metadata extras to MockMediaLibraryService and MockMediaBrowserCompatService and completed test cases for asserting
interoperability with a media1 or Media3 browser.

PiperOrigin-RevId: 480854842
(cherry picked from commit 006a519a0e83d5b9e4262a5bbc228c02b3c9cf5f)
2022-10-13 11:18:46 +00:00
christosts
ae5685427a MediaControllerWithMediaSessionCompatTest
Fix a race condition making test flaky.

PiperOrigin-RevId: 480104467
(cherry picked from commit cb3a6725083d4a1037c6081fe732ea999a5263c9)
2022-10-10 16:34:13 +00:00
christosts
48de6838b4 Minor naming cleanup in MediaControllerListenerTest
PiperOrigin-RevId: 480041937
(cherry picked from commit 6f8863fc112aa49cddf8d43bfb3da24f140ef33f)
2022-10-10 10:42:01 +00:00
christosts
20b086ce23 MediaControllerListenerTest: use local MediaController instances
Replace the instance-field MediaController with a local instance created
in each test.

PiperOrigin-RevId: 480039768
(cherry picked from commit ba1ecafb8f0db2a0e822eceffa724f1baae4a073)
2022-10-10 10:26:45 +00:00
bachinger
4d073799e0 Remove unofficial link from test case
PiperOrigin-RevId: 477101201
(cherry picked from commit 9e310150a91d9fb2d46e0e0298a9df41777b76eb)
2022-09-27 08:08:15 +00:00
tonihei
c91cdb49e0 Remove test that just times out
One of the tests in MediaBrowserListenerTest caused the remote
browser service to crash and then just timed out. As this asserts
nothing useful besides checking that the timeout method is working,
we can remove the test.

Crashing the remote browser service had the side effect of letting
subsequent tests in the same class fail because the previous session
was never released and was still present in the static MediaSession
SESSION_ID_TO_SESSION_MAP instance, which prevented the creation
of new sessions with the same id. This is only an issue in test
runs because a real process would also lose its static variables
when it crashes.

PiperOrigin-RevId: 476905337
(cherry picked from commit d2887d523773de75ed99403c22d634538f6c81df)
2022-09-26 15:39:47 +00:00
christosts
c2ccc62fb5 MediaControllerListenerTest: add bugs IDs in TODOs
PiperOrigin-RevId: 472974903
(cherry picked from commit 260aabb6e948f48edaa79f839e483c661f7d944b)
2022-09-08 13:42:17 +00:00
bachinger
1b7060776b Remove assertion that prevents masking of ad periods
The assertion asserts against a `Period` and an `AdPlaybackState` which actually
asserts against a resolved ad which is what `ExoPlayerImplInternal` does later and
what gives us a `SEEK_ADJUSTMENT`. However, this assertion is not required at the
moment of masking, because we are sure that the resolved seek results in a content
period and never an ad period.

#minor-release
Issue: androidx/media#122
PiperOrigin-RevId: 471827072
(cherry picked from commit 73f86682e94024c780564dbc287f06d47dfeca26)
2022-09-02 17:05:21 +00:00
tonihei
f3d48c21f4 Define CueGroup.EMPTY_TIME_ZERO for convenience
We create an empty CueGroup in many places as default or
where none is needed. Instead, we can define a constant
for this purpose and reuse it.

PiperOrigin-RevId: 467944841
(cherry picked from commit 59895646e03ee15aed5e80fb8e60b7f98a7afe5f)
2022-08-16 16:27:56 +00:00
christosts
19cc87c04f MediaNotificationManager: handle playback ended
When the player finishes playback and reaches the STATE_ENDED,
the notification remains visible with a pause button and the
service is kept in the foreground. This is a bug.

With this change, when the player reaches the STATE_ENDED, the
service is stopped from the foreground and a notification is shown
with a play button. If the play icon is tapped, the player will restart
playback of the last played item. Playing the last played item again
is the existing behavior when play/pause commands are received from
the legacy MediaSession (e.g. BT headset buttons).

#minor-release

Issue: google/ExoPlayer#112
PiperOrigin-RevId: 467231509
(cherry picked from commit 7a7e1eb23b4bbf7d0c6c15b2f484434e65cd2c68)
2022-08-12 16:53:36 +00:00
bachinger
1bee4f86fb Add interface version of MediaSessionStub
PiperOrigin-RevId: 464052708
(cherry picked from commit a28b3ef77843bb75938b2ca738ebedf0c29c1129)
2022-07-29 11:52:06 +00:00
bachinger
8c560d2115 Add interface version of MediaControllerStub
PiperOrigin-RevId: 463930162
(cherry picked from commit c8089ead42d940c550955f7786447ad87784b9df)
2022-07-28 21:45:49 +00:00
tonihei
561b83e282 Delay unbinding the controller until pending commands are handled.
Once a controller bound to a MediaSessionService unbinds, this service
may be destroyed immediately if this was the last bound controller and
the service isn't started in the foreground.

At the time of releasing the controller, there may still be pending
commands that need to be handled by the session service. These commands
may cause the session service to post a foreground notification to
keep it alive. So to avoid the destruction of the service while these
commands are still handled, we need to keep the controller bound.

We also add a timeout in case the session tasks are never completed
by the session implementation. In case the controller is destroyed,
the unbinding happens automatically by the system.

PiperOrigin-RevId: 463802220
(cherry picked from commit ac42b593cc3280b866d42cdc11d57bb031b39757)
2022-07-28 11:10:36 +00:00
ibaker
878279425b Annotate methods that always return this with @CanIgnoreReturnValue
It's always safe to ignore the result of these methods, because the
caller already has a reference to the returned value.

PiperOrigin-RevId: 462388947
(cherry picked from commit 2deb435625c7569cb0bd250848adaa846884dc50)
2022-07-21 15:24:07 +00:00
tonihei
29246fb1b2 Ensure pending commands are still sent in MediaController.release()
We currently clear all pending messages, including the one that flushes
pending commands to the MediaSession. To ensure all commands that have
been called before controller.release() are still sent, we can manually
trigger the flush message from the release call.

Related to handling the final flush because disconnecting the controller,
MediaSessionStub didn't post the removal of the controller to the
session thread, creating a race condition between removing the controller
and actually handling the flush.

Issue: androidx/media#99
PiperOrigin-RevId: 462342860
(cherry picked from commit ee209690cb54fc800cf3a213f5075c9aaf51463c)
2022-07-21 10:10:22 +00:00
tonihei
eb823a9ab7 Run MediaSessionStub commands in order
Some commands are run asynchronously and subsequent commands need
to wait until the previous one finished. This can be supported
by returning a Future for each command and using the existing
command execution logic to wait for each Future to complete.

As some MediaSessionStub code is now executed delayed to when it
was originally created, we also need to check if the session is
not released before triggering any actions or sending result codes.

Issue: androidx/media#85
PiperOrigin-RevId: 462101136
(cherry picked from commit 7cb7636ed954f0737aaac2f9cf556715a2ee9b37)
2022-07-20 10:34:22 +00:00
bachinger
a1fc19d3c5 Exclude tracks if COMMAND_GET_TRACKS is not available
Issue: androidx/media#102
#minor-release
PiperOrigin-RevId: 461891031
(cherry picked from commit 5bf9e2fb31d9cc1dea5152e63f738b8d03fcacb3)
2022-07-19 15:39:27 +00:00
bachinger
24bfe3a5e0 Implement getCurrentTracks in MediaController
After this change the current tracks are sent to the controller as part of
`PlayerInfo` and call `Listener.onTracksChanged()` in case of a change in tracks.

PiperOrigin-RevId: 461578695
(cherry picked from commit 9a895cd18f020a4f9df24c142406e91507a76605)
2022-07-18 10:47:57 +00:00
rohks
49f4c9342d Add timestamp to CueGroup
`TextRenderer` is updated to output `CueGroup`, which contains the presentation time of the cues, in microseconds.

PiperOrigin-RevId: 456531399
(cherry picked from commit 74d61bbffb834cdb50d003a8de66af0e094ef702)
2022-06-22 17:19:55 +01:00
christosts
a6fc6fac31 Ignore flaky test
PiperOrigin-RevId: 453168843
(cherry picked from commit 8d326312fba9ec36264815746c531ea9b28e2c28)
2022-06-06 11:35:12 +00:00
christosts
94e97fe5db De-flake test in MediaSessionPermissionTest
This change makes MediaSessionPermissionTest.removeMediaItems()
non-flaky. This is a quick fix though it'd be good to refactor this
test file.

PiperOrigin-RevId: 453162764
(cherry picked from commit 34ca3bc3c3b52b8dcfc531de76bc0b34f7a89c8c)
2022-06-06 10:42:08 +00:00
bachinger
14aced6304 Avoid out of bounds when setting less media items than in playlist
Issue: androidx/media#86
#minor-release
PiperOrigin-RevId: 455182232
(cherry picked from commit 8f844b32fdf4d41d6a5690e57e55d0c383ee7e3e)
2022-06-15 19:05:26 +00:00
tonihei
6791532778 Remove setMediaUri/onSetMediaUri
This code path is now completely redundant as the same effect can be
achieved by using player.setMediaItem.

PiperOrigin-RevId: 455115567
(cherry picked from commit 21d4e8581701e12743626f49823a667d9f05ed68)
2022-06-15 17:00:27 +00:00
tonihei
6ed3e40681 Support setMediaItem(s) in MediaControllerImplLegacy
These calls were not implemented so far as they require a mix of
initial prepareFrom/playFrom calls and addQueueItem. We can also
support clients without queue handling to set single MediaItems.

To make the calls consistent and predictable in the session,
we need to ensure that none of the play/pause/addQueueItem/
removeQueueItem/prepare/playFromXYZ/prepareFromXYZ are called
before the controller is prepared and has media.

#minor-release

PiperOrigin-RevId: 455110246
(cherry picked from commit b475f1f2daba8e0ed2497cbf17f4b834e58c59a4)
2022-06-15 16:52:51 +00:00
tonihei
35691bce98 Add COMMAND_SET_MEDIA_ITEM to Player.Commands
Some Player implementations have no playlist capability but can still
set a MediaItem for playback. Examples are a MediaController connected
to a legacy MediaSession, ExoPlayer up to 2.12 or MediaPlayer.

To indicate this capability, we need an allowed command in addition
to COMMAND_CHANGE_MEDIA_ITEMS that just allows to set a single item
that replaces everything that is currently played.

#minor-release

PiperOrigin-RevId: 453879626
(cherry picked from commit 5333c67d08ec22a1b5153af152b456d36099f401)
2022-06-09 18:36:35 +00:00
tonihei
f5dc99f596 Forward legacy controller onPlay/PrepareFromXY calls to onAddMediaItems
These legacy callbacks are currently forwarded to onSetMediaUri which
will be removed in the future.

Also make sure to only call player.prepare/play after the items have
been set.

The calls to onAddQueueItem are also forwarded to onAddMediaItems to
actually allow a session to resolve these items to playable media, which
wasn't possible so far.

PiperOrigin-RevId: 453625204
(cherry picked from commit bd126ec5c5497615572bcdf259278a899b4574f8)
2022-06-09 18:36:35 +00:00
ibaker
af91fdbf54 Add @deprecated javadoc to all @Deprecated @Override methods
This ensures the 'use X instead' message is easily visible in the
generated HTML for the overriding method. Currently it's not, e.g.:
https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/BasePlayer.html#getCurrentWindowIndex()

#minor-release

PiperOrigin-RevId: 452002224
(cherry picked from commit b8ca5b8951325ed89063b2e30e1c7fd3b78f5e97)
2022-05-31 13:51:49 +00:00
bachinger
85a936ecb1 Implement session extras for Media3 and legacy controllers
This provides an (unstable) API for apps to broadcast session extras
Bundle to all connected controllers and set the extras in the legacy
session.

Similar to the custom layout, the extras Bundle is not part of the
Media3 session state. This means that when a Media3 controller
connects to the session after the broadcast, the extras needs to be
sent to that controller in  `MediaSession.Callback.onPostConnect(MediaSession session, ControllerInfo controller)`.

PiperOrigin-RevId: 451871731
2022-05-30 16:52:43 +00:00
bachinger
bf3d81c262 Add missing tests for custom layout notification
PiperOrigin-RevId: 451859199
2022-05-30 16:51:08 +00:00
tonihei
581c6b5429 Remove MediaMetadata.mediaUrl
This value only existed to allow setting media URLs from external sources
(e.g. in a MediaController) so that a player can start playing this item.
Now that we have MediaItem.RequestMetadata.mediaUrl we can remove this value
from MediaMetadata because it's request metadata, not media metadata.

PiperOrigin-RevId: 451857413
2022-05-30 16:49:28 +00:00
tonihei
6b782d1011 Replace MediaItemFiller by asynchronous callback.
The MediaItemFiller is not flexible enough for most realworld usages
because:
 - it doesn't allow asynchronous resolution of MediaItems (e.g. to
   look up URIs from a database)
 - it doesn't allow to batch updates for multiple items or do more
   advanced customizations (e.g. expanding a mediaId representing
   a playlist to multiple items).

Both issues can be solved by passing in a list of items and
returning a ListenableFuture. The callback itself can also move
into MediaSession.Callback for consistency with the other
callbacks.

PiperOrigin-RevId: 451857319
2022-05-30 16:48:41 +00:00
tonihei
342be88d81 Improve playlist operation behavior of session test MockPlayer
The MockPlayer currently:
 - uses separate fields for single mediaItem vs multiple mediaItems
 - replaces all items on addMediaItem operations
 - does nothing on remove/move operations.

Fix all of this by using a single field that replicates the player
operations directly.

Some tests also need to be updated to make them more realistic
(for example only removing items from a playlist that have
previously been added).

PiperOrigin-RevId: 451857271
2022-05-30 16:47:44 +00:00
rohks
001090cc43 Migrate leaf listeners of Player to new onCues override
PiperOrigin-RevId: 449587030
2022-05-24 11:02:03 +01:00
ibaker
cd142872bb Rename MediaSession.Builder.setSessionCallback to setCallback
Follow-up to c78c1f5891

PiperOrigin-RevId: 449492810
2022-05-24 10:59:06 +01:00
ibaker
c78c1f5891 Rename nested session callback interfaces to just Callback
This is consistent with other nested callback/listener interfaces like
`Player.Listener`.

PiperOrigin-RevId: 449476261
2022-05-24 10:57:02 +01:00
ibaker
7c235d2b84 Remove all null-tolerant methods from BundleableUtil.
In most cases it's clearer to in-line these null-checks with ternary
operators.

PiperOrigin-RevId: 449474621
2022-05-24 10:56:01 +01:00
rohks
c728647290 Create new class to store cues and timestamp.
We need to pass timestamp for the list of cues so we are defining a new class CueGroup which will store both cues and timestamp.

PiperOrigin-RevId: 449212054
2022-05-24 10:49:48 +01:00