Commit graph

148 commits

Author SHA1 Message Date
Googler
8773b59fb5 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
(cherry picked from commit 15d3d74e16)
2022-09-07 15:56:07 +00:00
Googler
1bf431566f 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
(cherry picked from commit 3a2e0d3717)
2022-09-05 12:19:14 +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 73f86682e9)
2022-09-02 17:05:21 +00:00
rohks
422e317156 Provide methods to override notification fields
`contentTitle` and `contentText` can now be overridden.

Issue: androidx/media#150
PiperOrigin-RevId: 471287701
(cherry picked from commit a45df2fdcb)
2022-08-31 17:23:20 +00:00
rohks
4c29eee330 Switch incorrectly configured native multidex to legacy
Native multidex can only be used for binaries with minSdkVersion of 21 or higher, but minSdkVersion was specified to 16.

PiperOrigin-RevId: 470003836
(cherry picked from commit 5b3f320230)
2022-08-25 16:07:42 +00:00
Marc Baechinger
f73018a269 Merge pull request #157 from vanniktech:onAddMediaItems-example
PiperOrigin-RevId: 469410221
(cherry picked from commit ca41026c5b)
2022-09-30 16:56:19 +00:00
rohks
e7aee55fca Fix missing commas in documentation of DefaultMediaNotificationProvider
PiperOrigin-RevId: 468257769
(cherry picked from commit 6950f3aaa8)
2022-08-17 18:54:01 +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 59895646e0)
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 7a7e1eb23b)
2022-08-12 16:53:36 +00:00
bachinger
1bee4f86fb Add interface version of MediaSessionStub
PiperOrigin-RevId: 464052708
(cherry picked from commit a28b3ef778)
2022-07-29 11:52:06 +00:00
tonihei
7411a31e7b Merge pull request #109 from tzugen:patch-1
PiperOrigin-RevId: 464045351
(cherry picked from commit 61e4f92310)
2022-08-08 08:28:35 +00:00
bachinger
8c560d2115 Add interface version of MediaControllerStub
PiperOrigin-RevId: 463930162
(cherry picked from commit c8089ead42)
2022-07-28 21:45:49 +00:00
christosts
60b334cd01 Minor: Change URL in test
Use a URL with a `.test` tld (RFC 2606) to make it clear
it's an testing URL.

PiperOrigin-RevId: 463852174
(cherry picked from commit 4713c7fea8)
2022-07-28 16:12:28 +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 ac42b593cc)
2022-07-28 11:10:36 +00:00
bachinger
38a133b23a Clean up hashCode/equals of SessionTokenImplBase
#minor-release

PiperOrigin-RevId: 463338680
(cherry picked from commit 2bde3f1e31)
2022-07-26 15:10:46 +00:00
bachinger
5a4e244d94 Normalize constructors of SessionTokenImplBase/SessionTokenImplLegacy
#minor-release

PiperOrigin-RevId: 463328436
(cherry picked from commit 428fc89635)
2022-07-26 14:12:19 +00:00
christosts
faf1f35feb 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
(cherry picked from commit dd2c16bc45)
2022-07-22 09:05:10 +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 2deb435625)
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 ee209690cb)
2022-07-21 10:10:22 +00:00
ibaker
0667c74dc5 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
(cherry picked from commit 287c757944)
2022-07-21 09:20:33 +00:00
tonihei
33c5aa7a88 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
(cherry picked from commit 4a4a74edff)
2022-07-20 13:47:47 +00:00
christosts
62a2d76d00 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
(cherry picked from commit 436ff6d86a)
2022-07-20 11:41:30 +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 7cb7636ed9)
2022-07-20 10:34:22 +00:00
tonihei
d84662e5ce 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
(cherry picked from commit 45f1f5b378)
2022-07-20 08:56:08 +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 5bf9e2fb31)
2022-07-19 15:39:27 +00:00
bachinger
c37c6812d6 Remove unused argument
PiperOrigin-RevId: 461830378
(cherry picked from commit e8b5aad3d7)
2022-07-19 09:16:55 +00:00
tonihei
481205a88f 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
(cherry picked from commit dee80788e4)
2022-07-19 08:59:30 +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 9a895cd18f)
2022-07-18 10:47:57 +00:00
olly
6eb30ce233 Add TODOs for registerReceiver calls without flag
PiperOrigin-RevId: 461165173
(cherry picked from commit 9271572e95)
2022-07-15 10:34:53 +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 74d61bbffb)
2022-06-22 17:19:55 +01:00
bachinger
87b817b0f9 Fix incorrect link tags
PiperOrigin-RevId: 459215618
(cherry picked from commit 87adb88f57)
2022-07-06 11:02:12 +00:00
bachinger
3de3f41757 Document custom commands in the DefaultMediaNotificationProvider
Issue: androidx/media#103
#minor-release
PiperOrigin-RevId: 458465479
(cherry picked from commit 2c0806814b)
2022-07-01 14:27:24 +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 8f844b32fd)
2022-06-15 19:05:26 +00:00
bachinger
5ebc07ce76 Updating translations
#minor-release

PiperOrigin-RevId: 455128997
(cherry picked from commit 958105c91c)
2022-06-15 17:00:36 +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 21d4e85817)
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 b475f1f2da)
2022-06-15 16:52:51 +00:00
bachinger
e3e92b2448 Suppress lint errors RestrictedApis in lib-session
PiperOrigin-RevId: 454943102
(cherry picked from commit 252ae4c7a3)
2022-06-15 16:52:50 +00:00
bachinger
7c0b787bdb Add session URI to Intent used with the notification
The service handles three different types of `Intents`. Custom command and media
command Intents created by the library and media button event Intents from other
sources.

Media commands from the library as well as from external sources have the action
set to `android.intent.action.MEDIA_BUTTON`. If the data URI is set and can be
used to identify a session then it is a library Intent. If the Intent is coming
from an external KeyEvent, the service implementation is asked which session to use
by calling `onGetSession(controllerInfo)` with the controller info being an
anonymous legacy controller info.

Intents representing a custom command are always coming from the library and hence
always have a data URI.

Issue: androidx/media#82
PiperOrigin-RevId: 453932972
(cherry picked from commit 8b592fc77a)
2022-06-09 18:36:35 +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 5333c67d08)
2022-06-09 18:36:35 +00:00
christosts
35c9585f5f Avoid using ConcurrentHashMap
Use Collections.synchronizedSet() instead of creating a set from a
ConcurrentHashMap because ConcurrentHashMap has a bug in APIs 21/22
that can result in lost updates.

PiperOrigin-RevId: 453696565
(cherry picked from commit d506c709c9)
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 bd126ec5c5)
2022-06-09 18:36:35 +00:00
bachinger
ad5788ef37 Use resource ID from drawable.xml as the notification icon
Issue: androidx/media#66
Issue: androidx/media#65

#minor-release

PiperOrigin-RevId: 452004492
(cherry picked from commit 839d4f4390)
2022-05-31 13:51:49 +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 b8ca5b8951)
2022-05-31 13:51:49 +00:00
bachinger
40f5fb55cc Add constants for custom actions UI customization
PiperOrigin-RevId: 451875964
2022-05-30 16:54:22 +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
7af9f02067 Add a constant for the legacy controller version
PiperOrigin-RevId: 451857459
2022-05-30 16:50:22 +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
c814f791d7 Add sessionImpl to PostSessionTask
In some cases it's helpful to have access to the session
(e.g. to get the PlayerWrapper) from within the PostSessionTask
implementations. This change forwards the existing sessionImpl
instance to all these callbacks.

PiperOrigin-RevId: 451857191
2022-05-30 16:46:49 +00:00
bachinger
8aec86bde0 Fix typo
PiperOrigin-RevId: 451824740
2022-05-30 16:43:34 +00:00