Commit graph

268 commits

Author SHA1 Message Date
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
tonihei
69cfba7c53 Correctly filter PlayerInfo by available getter commands.
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
2023-01-23 12:22:33 +00:00
tonihei
c90ca7ba5f Make availableCommands known when bundling PlayerInfo
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
2023-01-18 12:02:09 +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
tonihei
664ab72d09 Remove unneccesary parameter taking Player.Command
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
2023-01-17 02:07:14 +00:00
tonihei
86a95c2a4a Correctly map deprecated methods in MediaController to replacement
This avoids throwing exceptions for correct (but deprecated) Player
method invocations.

PiperOrigin-RevId: 502341428
2023-01-17 02:06:29 +00:00
tianyifeng
0d0cd78626 Catch FgSStartNotAllowedException when playback resumes
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
2023-01-17 02:00:03 +00:00
bachinger
a2cf222117 Improve Java doc about how to override notification drawables
Issue: androidx/media#140
PiperOrigin-RevId: 501288267
2023-01-17 01:51:42 +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
rohks
578f2de48f Initialise fields used for bundling as String directly
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
2023-01-10 18:33:20 +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
ibaker
14947539e5 Remove TODO from ControllerInfo - the existing approach is fine
PiperOrigin-RevId: 496398934
2022-12-21 15:21:37 +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
f768ff970c Reduce log output for failing bitmap loads
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
2022-12-12 10:58:23 +00:00
Googler
69093db7f5 Decomission ControllerInfoProxy in favor of ControllerInfo.
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
2022-12-12 10:45:07 +00:00
bachinger
2a07a0b445 Use the artist as the subtitle of the legacy media description
The Bluetooth AVRCP service expects the metadata of the item currently
being played to be in sync with the corresponding media description in
the active item of the queue. The comparison expects the metadata values
of `METADATA_KEY_TITLE` and `METADATA_KEY_ARTIST` [1] to be equal to the
`title` and `subtitle` field of the `MediaDescription` [2] of the
corresponding queue item.

Hence we need to populate the media description accordingly to avoid the
BT service to delay the update for two seconds and log an exception.

[1] https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/android/app/src/com/android/bluetooth/audio_util/helpers/Metadata.java;l=120
[2] https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java;l=258

Issue: androidx/media#148
PiperOrigin-RevId: 491877806
2022-12-12 10:39:58 +00:00
rohks
f3e450e783 Add public constructors to DefaultMediaNotificationProvider
Issue: androidx/media#213

Without a public constructor, it is not possible to extend this class and override its method.

PiperOrigin-RevId: 491673111
2022-11-29 18:54:38 +00:00
tianyifeng
80927260fd Handle the bitmap loading result with applicationHandler
Before this change, the bitmap loading result with mainHandler, in which we set the metadata to `MediaSessionCompat`. However, the `MediaSessionCompat` is not thread safe, all calls should be made from the same thread. In the other calls to `MediaSessionCompat`, we ensure that they are on the application thread (which may be or may not be main thread), so we should do the same for `setMetadata` when bitmap arrives.

Also removes a comment in `DefaultMediaNotificationProvider` as bitmap request caching is already moved to CacheBitmapLoader.

PiperOrigin-RevId: 490524209
2022-11-24 14:48:50 +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
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
c41a5c8420 Do not require package visibility when obtaining SessionTokens
The only reason this is required at the moment is to set the
process UID field in the token, that is supposed to make it easier
for controller apps to identify the session. However, if this
visibility is not provided, it shouldn't stop us from creating
the controller for this session.

Also docuement more clearly what UID means in this context.

PiperOrigin-RevId: 490184508
2022-11-22 12:05:03 +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
tonihei
22ccc1a128 Mark broadcast receivers as not exported
They are called from the system only and don't need to be exported
to be visible to other apps.

PiperOrigin-RevId: 489210264
2022-11-22 09:54:45 +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
bachinger
bae509009b Add bundling exclusions with unit tests
The exclusion will be used in a follow-up CL when sending PlayerInfo updates.

#minor-release

PiperOrigin-RevId: 488939258
2022-11-22 09:45:56 +00:00
bachinger
e1eb8b6dd8 Add pending sequence before sending the remote session task
#minor-release

PiperOrigin-RevId: 488885069
2022-11-16 12:19:48 +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
samrobinson
59aedcf309 Handle buffers in DefaultAudioSink with AudioProcessingPipeline.
PiperOrigin-RevId: 488412695
2022-11-16 12:07:58 +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
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
b24161a6f6 Avoid notifying connection twice from MediaControllerImplLegacy.
The connection to a legacy MediaSession may receive additional
onSessionReady callbacks that are treated as additional state updates.
We currently also set the "notifyConnected" flag for these updates
even though we are connected already, causing an IllegalStateException.

Fix the exception by not setting this flag.

We can also remove the wording about "locked" updates since this class
operates everything on a single application thread.

Issue: androidx/media#49
PiperOrigin-RevId: 487487286
2022-11-10 14:52:55 +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
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
rohks
2633f37a2f Update notification when timeline changes
Notification buttons for next/previous should change based on the new index of the currently played media item after another media item is added or removed from a playlist.

Issue: androidx/media#130
PiperOrigin-RevId: 485869144
2022-11-08 11:24:36 +00:00
christosts
8db6b71805 Clean imports in MediaControllerImplLegacy
Remove static imports to constants and imports to intdefs, to make the
code more readable.

PiperOrigin-RevId: 485592288
2022-11-08 11:22:19 +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
andrewlewis
3069d8130b Upgrade dackka and fix some generation errors
#minor-release

PiperOrigin-RevId: 484483080
2022-10-31 11:46:58 +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
tianyifeng
3f69df72db Add injection of BitmapLoader from MediaSession.
* Add `BitmapLoader` in `MediaSession.Builder` and `MediaLibrarySession.Builder`.
* Pass `BitmapLoader` into the constructor of `MediaSession`, `MediaSessionImpl`, `MediaLibrarySession` and `MediaLibrarySessionImpl`.
* Add an interface method `loadBitmapFromMetadata(MediaMetadata)` in `BitmapLoader`.
* Remove the reference of `BitmapLoader` in `DefaultMediaNotificationProvider`.

PiperOrigin-RevId: 483654596
2022-10-31 11:32:30 +00:00
ibaker
026aea7d3d Create NotificationChannel in DefaultMediaNotificationProvider.Api26
The inner class avoids a verification failure, which can lead to slower
execution at runtime.

PiperOrigin-RevId: 483639417
2022-10-31 11:31:31 +00:00
microkatz
e2a77f7be9 Merge pull request #141 from tzugen:patch-4
PiperOrigin-RevId: 483395026
2022-10-31 11:28:21 +00:00
bachinger
a47f530b92 Minor simplification when setting metadata to platform session
PiperOrigin-RevId: 482805730
2022-10-24 10:52:38 +00:00
tianyifeng
ca4edff1fd Add CacheBitmapLoader in the session module
* Add `CacheBitmapLoader`.
* Add `CacheBitmapLoaderTest`.
* Remove the `BitmapLoadRequest` and some bitmap caching logic in `DefaultMediaNotificationProvider` since we moved all of them in `CacheBitmapLoader`.
* Modify `DefaultMediaNotificationProviderTest`.

PiperOrigin-RevId: 482787445
2022-10-24 10:51:32 +00:00
christosts
601eaba7a6 Use Service.stopForeground(int) on API 24+
The MediaNotficationManager stops the service from the foreground
calling Service.stopForeground(boolean) which is deprecated in API 33.
This change calls Service.stopForeground(int), which was added in API
24.

#minor-release

PiperOrigin-RevId: 482190332
2022-10-24 10:41:47 +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
bachinger
006a519a0e 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
2022-10-17 15:56:30 +00:00
christosts
36e12fbadb MediaControllerImplBase: clean imports
Remove static imports to constants and imports to intdefs, to make the
code more readable.

PiperOrigin-RevId: 479594144
2022-10-17 15:40:28 +00:00
aquilescanta
0beccb6e14 Fix typo in MediaController javadoc
PiperOrigin-RevId: 479268879
2022-10-17 15:35:19 +00:00
Googler
7783c6e4f7 Allow using different notification IDs for different media sessions
When a media service currently produces multiple media sessions, the notification of the second session overwrites the notification of the first one, because all sessions use the same notification ID. When we use different notification IDs for different sessions, multiple media notifications can be up at the same time, which means that they can both be controlled at the same time.

PiperOrigin-RevId: 478709069
2022-10-17 15:27:19 +00:00
bachinger
acd9e581c4 Don't start the service in the foreground with a pause intent
`PlaybackStateCompat.toKeyCode(command)` was replaced by our
own implementation of `toKeyCode()`. The legacy implementation used PLAY and PAUSE, while the new implementation uses PLAY_PAUSE. This made `pause` a pending intent that attempt to start the service in the foreground, but `service.startForeground()` won't be called in `MediaNotificationManager.updateNotificationInternal` when paused.

PiperOrigin-RevId: 476895752
2022-09-30 18:21:15 +00:00
bachinger
74124f48ea Call callback future listeners on app handler
Calling maybeUpdateLegacyErrorState potentially creates a new legacy playback
state which involves calling player methods. This change makes sure that the call
sites of `maybeUpdateLegacyErrorState` are called on the app thread as enforced by
the library.

PiperOrigin-RevId: 476406282
2022-09-30 18:19:17 +00:00
Googler
15d3d74e16 Clarify exception message.
The exception fires when intent resolution fails to find a service which declares an appropriate intent-filter. The existing message is confusing; it's trying to say that the service couldn't be found but the double negative renders it incorrect.

#cleanup
#minor-release

PiperOrigin-RevId: 472736740
2022-09-30 17:39:56 +00:00
Googler
3a2e0d3717 Fix 4 ErrorProneStyle findings:
* Non-standard parameter comment; prefer `/* paramName= */ arg`
  (see http://go/bugpattern/ParameterComment) (2 times)
* This catch block catches an exception and re-throws another, but swallows the caught exception rather than setting it as a cause. This can make debugging harder.
  (see http://go/bugpattern/UnusedException)
* This comment contains Javadoc or HTML tags, but isn't started with a double asterisk (/**); is it meant to be Javadoc?
  (see http://go/bugpattern/AlmostJavadoc)

This CL looks good? Just LGTM and Approve it!
This CL doesn’t look good? This is what you can do:
* Revert this CL, by replying "REVERT: <provide reason>"
* File a bug under go/error-prone-bug for category ErrorProneStyle if there's an issue with the CL content.
* File a bug under go/rosie-bug if there's an issue with how the CL was managed.
* Revert this CL and not get a CL that cleans up these paths in the future by
replying "BLOCKLIST: <provide reason>". This is not reversible! We recommend to
opt out the respective paths in your CL Robot configuration instead:
go/clrobot-opt-out.

This CL was generated by CL Robot - a tool that cleans up code findings
(go/clrobot). The affected code paths have been enabled for CL Robot in //depot/google3/java/com/google/android/libraries/media/METADATA which is reachable following include_presubmits from //depot/google3/third_party/java_src/android_libs/media/METADATA.
Anything wrong with the signup? File a bug at go/clrobot-bug.

#codehealth

Tested:
    Local presubmit tests passed.
PiperOrigin-RevId: 472255768
2022-09-30 17:27:48 +00:00
bachinger
73f86682e9 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
2022-09-30 17:24:00 +00:00
rohks
a45df2fdcb Provide methods to override notification fields
`contentTitle` and `contentText` can now be overridden.

Issue: androidx/media#150
PiperOrigin-RevId: 471287701
2022-09-30 17:18:28 +00:00
Marc Baechinger
ca41026c5b Merge pull request #157 from vanniktech:onAddMediaItems-example
PiperOrigin-RevId: 469410221
2022-09-30 16:56:19 +00:00
rohks
6950f3aaa8 Fix missing commas in documentation of DefaultMediaNotificationProvider
PiperOrigin-RevId: 468257769
2022-09-30 16:47:16 +00:00
tonihei
59895646e0 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
2022-09-30 16:43:22 +00:00
christosts
7a7e1eb23b 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
2022-09-30 16:36:20 +00:00
Niklas Baudy
31e69d2dac MediaSession.Callback: Document an example when onAddMediaItems is called. 2022-08-19 15:35:59 +02:00
Rohit Kumar Singh
7109d284a7
Revert "DefaultMediaNotificationProvider: Fix missing comma in documentation." 2022-08-17 17:00:56 +01:00
Niklas Baudy
42b5a6b211 DefaultMediaNotificationProvider: Fix missing comma in documentation. 2022-08-15 20:05:31 +02:00
birdbird
22efef2dea
Disable badge in API 26 and 27 2022-08-04 07:20:02 +02:00
bachinger
a28b3ef778 Add interface version of MediaSessionStub
PiperOrigin-RevId: 464052708
2022-08-08 08:32:29 +00:00
tonihei
61e4f92310 Merge pull request #109 from tzugen:patch-1
PiperOrigin-RevId: 464045351
2022-08-08 08:28:35 +00:00
bachinger
c8089ead42 Add interface version of MediaControllerStub
PiperOrigin-RevId: 463930162
2022-08-08 08:25:47 +00:00
tonihei
ac42b593cc 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
2022-08-08 08:19:35 +00:00
bachinger
2bde3f1e31 Clean up hashCode/equals of SessionTokenImplBase
#minor-release

PiperOrigin-RevId: 463338680
2022-08-08 08:08:41 +00:00
bachinger
428fc89635 Normalize constructors of SessionTokenImplBase/SessionTokenImplLegacy
#minor-release

PiperOrigin-RevId: 463328436
2022-08-08 08:07:47 +00:00
christosts
dd2c16bc45 DefaultMediaNotificationProvider: limit requests to load same bitmap
The DefaultMediaNotificationProvider caches the last loaded artwork
bitmap so that the bitmap isn't loaded again when the notification is
updated, e.g., the player is transiting from playing to paused. However,
loading bitmap requests for bitmaps that are already being loaded are
not suppressed. For example, if the notification is updated while the
artwork is still downloading, the same artwork might be downloaded
multiple times.

This change suppresses a bitmap load request if the same artwork is
still being loaded, to avoid additional artwork downloads.

#minor-release

PiperOrigin-RevId: 462572221
2022-08-08 07:59:04 +00:00
ibaker
2deb435625 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
2022-08-08 07:55:25 +00:00
birdbird
836023589e
Update JavaDoc accordingly 2022-07-26 20:12:12 +02:00
tonihei
ee209690cb 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
2022-07-21 13:00:20 +00:00
ibaker
287c757944 Slightly disentangle MediaBrowser/Controller(Impl)Base/Legacy
These constructors are currently very intertwined, passing `this`
references from the constructor of one to the constructor of another
before the first constructor is complete (and so the `this` reference
isn't really valid yet).

This change uses checker framework `@UnderInitialization` and
`@NotOnlyInitialized` annotations to make it more clear that the
references are not available yet. For the one 'direct' access needed
in the second constructor (calling `getApplicationLooper()`) we now
pass the `applicationLooper` directly alongside (to avoid needing to
dereference the reference 'too early').

This change also ensures that where a class hierarchy has a
'dependent' class hierarchy, the 'subclass' instance is always used
(by both subclass and superclass) without casting or manually hiding
the superclass field, by defining an overridable `getFoo()` method
instead and always using it.

#minor-release

PiperOrigin-RevId: 462335043
2022-07-21 12:59:23 +00:00
tonihei
4a4a74edff Rename seq to sequenceNumber in MediaSessionStub
"seq" is not a well-defined abbreviation and the value is
also an integer, so sequenceNumber is better than just sequence.

PiperOrigin-RevId: 462129581
2022-07-21 12:56:13 +00:00
christosts
436ff6d86a Make DefaultMediaNotificationProvider more configurable
Add a Builder to constructor DefaultMediaNotificationProvider. The
Builder can also set the provider's:
- notification ID
- notification channel ID
- notification channel name

The change adds an API for apps to set the small icon in notifications.

#minor-release
Issue: androidx/media#104
PiperOrigin-RevId: 462111536
2022-07-21 12:54:59 +00:00
tonihei
7cb7636ed9 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
2022-07-21 12:54:06 +00:00
tonihei
45f1f5b378 Properly chain commands in MediaSessionStub
The commands currently use a task and a postTask that are chained
together manually. In some cases, e.g. when adding MediaItems,
the postTask is already a chain of commands in itself.

To allow using the entire command handling as a single task
(for simplified queueing), we can change the implementation to
always create a single task. If multiple subtasks need to be
chained together, we can do that by wrapping the method calls.
In case a task is asynchronous, we can also use Futures to
chain them together.

Overall, this is just a refactoring and changes no logic.

Issue: androidx/media#85
PiperOrigin-RevId: 462085724
2022-07-21 12:53:11 +00:00
bachinger
5bf9e2fb31 Exclude tracks if COMMAND_GET_TRACKS is not available
Issue: androidx/media#102
#minor-release
PiperOrigin-RevId: 461891031
2022-07-21 12:50:29 +00:00
bachinger
e8b5aad3d7 Remove unused argument
PiperOrigin-RevId: 461830378
2022-07-21 12:45:10 +00:00
tonihei
dee80788e4 Use Futures for MediaSession command queue instead of Runnables
Some commands may be asynchronous and subsequent commands need to
wait for them to complete before running. This change updates the
queue to use (and listen to) Futures instead of calling Runnables
directly. The commands are currently still added as Runanbles
though, so this change is a no-op.

Also moves the permission check in MediaSessionImpl to before
queueing the command because the permission should be check at
the time of calling the method.

When executing the comamnds in the queue, we need to be careful
to avoid recursion in the same thread (which happens when both
the Future is immediate and running on the correct thread already).
To avoid recursion, we detect this case and loop the commands
instead.

Issue: androidx/media#85
PiperOrigin-RevId: 461827264
2022-07-21 12:44:16 +00:00
bachinger
9a895cd18f 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
2022-07-21 12:40:39 +00:00
olly
9271572e95 Add TODOs for registerReceiver calls without flag
PiperOrigin-RevId: 461165173
2022-07-15 12:19:04 +00:00
bachinger
87adb88f57 Fix incorrect link tags
PiperOrigin-RevId: 459215618
2022-07-07 16:44:05 +00:00
birdbird
6016418c33
Support file schemes in SimpleBitmapLoader
Fixes #108
2022-07-06 07:17:46 +02:00
bachinger
2c0806814b Document custom commands in the DefaultMediaNotificationProvider
Issue: androidx/media#103
#minor-release
PiperOrigin-RevId: 458465479
2022-07-04 19:51:25 +00:00
rohks
74d61bbffb Add timestamp to CueGroup
`TextRenderer` is updated to output `CueGroup`, which contains the presentation time of the cues, in microseconds.

PiperOrigin-RevId: 456531399
2022-06-27 10:38:20 +01:00