Commit graph

264 commits

Author SHA1 Message Date
Googler
1ef0b7c616 Automated Code Change
PiperOrigin-RevId: 630995654
2024-05-06 04:04:20 -07:00
tonihei
d0d6ce52a5 Import androidx.media
This imports all the classes and resources needed by our code.

We still have the nominal dependency on the artifact as we need
to access the Parcelable CREATORs of MediaSessionCompat.Token,
MediaDescriptionCompat, RatingCompat and MediaBrowserCompat.MediaItem.

Mechanical import steps:
 - Put all files under a new 'legacy' package and change all import
   statements accordingly.
 - Reformat to adhere to Media3 java style guide
 - Remove all existing @RestrictTo annotations and replace them with
   top-level @RestrictTo(LIBRARY) on all classes in the new package.
 - Remove @NonNull annotations and fixed nullability test errors
 - Fix HTML javadoc build errors
 - Fix Lint errors (but not warnings)

The code still contains many lint warnings that will be fixed
separately.

PiperOrigin-RevId: 627999285
2024-04-25 01:56:23 -07:00
tonihei
43d1fa933c Remove flakiness from MCCPlaybackStateCompatActionsWithMediaSessionTest
The tests were reigstering a listener to wait for the first event, but
this first even may have happened already by the time the listener is
registered. Instead we can wait until the controller is connected and
assume that the initial state already arrived.

PiperOrigin-RevId: 627683245
2024-04-24 04:27:44 -07:00
tonihei
e1c62df256 Remove media1 public API dependencies from session module
This is the preparation to import the media1 classes as
private copies into media3.

- Reword Javadoc to use @code instead of @link to media1 types. This
  avoids accidentally linking to the future internal types.
- Use fully qualified names for the converter methods to and from
  MediaSessionCompat.Token to ensure they keep the publicly available
  type.
- Add new public variable that is directly referenced from our code
  instead of referring the the media1 equivalent.
- Clean up tests that are using media1 types to make assertions on
  media3 fields and vice versa (mostly when using LegacyConversions
  in the test method). This also makes the tests more DAMP than DRY.
  (also moved LegacyConversionsTest to a unit test as it doesn't test
  cross-process communication)

PiperOrigin-RevId: 626000082
2024-04-18 05:33:10 -07:00
ibaker
fd268eed46 Remove unecessary re-setting of group from session Gradle files
These TODOs precede <unknown commit> when the group was set in the top-level
`build.gradle` file.

Issue: androidx/media#1215
PiperOrigin-RevId: 618835040
2024-03-25 07:33:05 -07:00
ibaker
d997ba367c Rollback of 7cffae9cd0
PiperOrigin-RevId: 618799275
2024-03-25 04:30:55 -07:00
tonihei
0e42c8945f Automatically add icon drawables for icon constants
Having a default icon available allows apps to only specify the
icon constant without having to define an icon drawable themselves
as Media3 can fill in the icon resource for backwards compatibility.

The switch util method allows R8 to easily remove unused icons, so
having default icons won't affect APK size unless the constants are
used to set up the CommandButtons.

PiperOrigin-RevId: 614623909
2024-03-11 05:06:21 -07:00
ibaker
7cffae9cd0 Apply common_library_config in test_session_current/build.gradle
This is the only `build.gradle` file that currently doesn't apply this
config, and it seems to lead to desugaring errors when apps depend on
the library locally.

PiperOrigin-RevId: 613559535
2024-03-07 06:14:25 -08:00
tonihei
9abe9e2a97 Refine auto-update logic of CommandButton.isEnabled
We currently update this value for controllers to match the
availability of the associated command. This however makes it
impossible to mark a button as unavailable if the command is
available. This can be refined by only setting the 'enabled'
field to false if the command is not available, not the other
way round. And we should also enable the button by default as
disabling is the unusual case not many apps will use.

In addition, this change fixes missing update logic when the
player commands changed and it adds some additional test coverage
for all these cases.

PiperOrigin-RevId: 612881016
2024-03-05 10:08:17 -08:00
tianyifeng
1bdc58de0b Avoid position jumping back when controller replaces the current item
When the controller replaces the current item, the masking position will be changed to the default position of the new item for a short while, before the correct position comes from the session. This will interrupt the current position fetched from the controller when the playback doesn't interrupted by the item replacing.

Issue: androidx/media#951

#minor-release

PiperOrigin-RevId: 611417539
2024-02-29 04:07:17 -08:00
Copybara-Service
fb7438378d Merge pull request #983 from MGaetan89:min_api_19
PiperOrigin-RevId: 607319987
2024-02-15 07:00:17 -08:00
bachinger
4777d62d31 Rollback of 8e2869278c
PiperOrigin-RevId: 607264513
2024-02-15 02:35:12 -08:00
asinclair
8e2869278c Internal Cleanup
PiperOrigin-RevId: 607117264
2024-02-14 15:06:10 -08:00
bachinger
89571c0a92 Check whether the session activity pending intent is an activity
PiperOrigin-RevId: 606613694
2024-02-13 07:28:31 -08:00
Gaëtan Muller
973b717914 Remove unnecessary SDK_INT checks 2024-02-13 10:26:19 +00:00
tonihei
adc23e8e8b Add icon constants to CommandButton
These allow to set the icon in a standardized way without needing
custom bitmaps or resources. For now, this is just additional
information without backwards-compatible icons or implications.

The same value gets written to the platform session via a new
extras key that can be read and set from sessions not using Media3
yet.

PiperOrigin-RevId: 605670988
2024-02-09 10:37:12 -08:00
tonihei
ed5b7004b4 Replace or suppress deprecated usages
Many usages are needed to support other deprecations and some
can be replaced by the recommended direct alternative.

Also replace links to deprecated/redirected dev site

PiperOrigin-RevId: 601795998
2024-01-26 10:06:18 -08:00
tonihei
c64b271f07 Check int and float parameters from external apps for validity
Some player method calls sent from MediaControllers accept int
or float values with a very clear API contract that disallows
some values. Filtering by these values early avoids calling a
Player implementation with invalid values.

PiperOrigin-RevId: 600413993
2024-01-22 04:08:42 -08:00
bachinger
4974f960e7 Fix broadcasting notifyChildrenChanged for legacy controllers
When broadcasting a notifyChildrenChanged event, the task for legacy
controllers was sent to the broadcasting callback. This would
technically work, but because the subscription list is maintained
with specific controllers, the broadcast controller isn't subscribed
and hence the call wasn't executed.

This change calls the overloaded method for a specific controller
for each connected controller. Making sure (only) subscribed
controllers are notified.

Issue: androidx/media#644
PiperOrigin-RevId: 590904037
2023-12-14 05:20:39 -08:00
bachinger
7f9b02080a Make the media notification controller marker key visible
An app that uses the `MediaSession` without a `MediaSessionService` may
want to connect a media notification controller on it own. To avoid apps
using a string literal, the key should be exposed as public.

PiperOrigin-RevId: 589875603
2023-12-11 10:57:00 -08:00
bachinger
a063d137b4 Add session extras to the state of the controller
This change adds `MediaController.getSessionExtras()` through
which a controller can access the session extras.

The session extras can be set for the entire session when
building the session. This can be overridden for specific
controllers in `MediaSession.Callback.onConnect`.

PiperOrigin-RevId: 584430419
2023-11-21 14:32:33 -08:00
bachinger
ec478138ba Add test case to test position conversion when POSITION_UNKNOWN
PiperOrigin-RevId: 584261559
2023-11-21 02:24:30 -08:00
rohks
ffbaa090aa Use .test top level domain for test URI
PiperOrigin-RevId: 583951327
2023-11-20 02:00:30 -08:00
rohks
6df240877c Populate MediaMetadata.extras to MediaMetadataCompat
Ensures backward compatibility.

Issue: androidx/media#802
PiperOrigin-RevId: 583425114
2023-11-17 10:25:10 -08:00
tonihei
312203d38b Deprecate Bundleable and Bundleable.Creator
Both interfaces are not really needed as the methods can be called
on the respective classes directly. This also avoid error-prone
situations where classes define to/fromBundle methods with parameters
that should be used instead of the parameter-less version.

Also deprecate all existing CREATOR static instances and make the
corresponding fromBundle method public where needed.

PiperOrigin-RevId: 579189766
2023-11-03 08:27:21 -07:00
tonihei
d4e5ab2c4d Make BundleableUtil more generic by taking Function parameters
BundleableUtil is the only class that really depends on the type
inheritence from Bundleable. However, it only needs this as a way
to define Function<T, Bundle> and Function<Bundle, T>, which could
just be passed in as parameters as it's already done for some of
these methods.

Also rename the class to BundleCollectionUtil accordingly.

PiperOrigin-RevId: 578791946
2023-11-02 03:17:17 -07:00
ibaker
72b7019578 Split media1/media3 conversion methods out of MediaUtils
Android Studio removed some nested imports, but I think the extra
qualification at the usage site is actually mostly helpful, so I'm
leaving it as-is.

PiperOrigin-RevId: 578518880
2023-11-01 08:04:21 -07:00
tianyifeng
84022eacc5 Put the custom keys in MediaMetadataCompat to MediaMetadata.extras
PiperOrigin-RevId: 578473874
2023-11-01 04:30:10 -07:00
bachinger
a79d44edc5 Use MediaSessionImpl.onMediaButtonEvent() to dispatch key events
This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: androidx/media#12
Issue: androidx/media#159
Issue: androidx/media#216
Issue: androidx/media#249

#minor-release

PiperOrigin-RevId: 575231251
2023-10-20 08:55:15 -07:00
tonihei
bfd1a2724c Add missing command checks to playback resumption flow
Player methods shouldn't be called if they are not available and the
entry point to the playback resumption flow only checks
COMMAND_PLAY_PAUSE.

#minor-release

PiperOrigin-RevId: 574834148
2023-10-19 05:39:21 -07:00
tonihei
f0cab4d03e Rollback of 64bd3bcad3
PiperOrigin-RevId: 574766164
2023-10-19 01:06:08 -07:00
tonihei
db86932781 Use DataSourceBitmapLoader by default
This replaces the SimpleBitmapLoader that can now be deprecated
as it's fully unused and doesn't provide any additional functionality.

#minor-release

PiperOrigin-RevId: 574454636
2023-10-18 06:18:32 -07:00
Googler
1a43aa3602 Rollback of 64bd3bcad3
PiperOrigin-RevId: 574290408
2023-10-17 16:01:10 -07:00
bachinger
64bd3bcad3 Send media button events from service directly using MediaSessionImpl
Media button event coming from the `MediaSessionService` are delegated
to the `MediaSessionImpl` and then sent to the session by using the
`MediaSessionStub` directly instead of using the `MediaController`
API.

Splitting the `MediaController.Listener` and `Player.Listener` in
`MediaNotificationManager` got reverted, and both listener are set to the
controller as before. This reverts the change that introduced a
different timing behaviour. It still holds, that a listener
registered on a `MediaController` that calls a method like `play()` is
called immediately and before the call has arrived at the player. This
change works around this behaviour from the library side by calling
`MediaSessionStub` directly with a `ControllerInfo`.

#minor-release

PiperOrigin-RevId: 573918850
2023-10-16 13:52:30 -07:00
bachinger
d5f093f43c Send ConnectionState as in-process bundle if possible
#minor-release

PiperOrigin-RevId: 573849858
2023-10-16 10:15:34 -07:00
bachinger
f53e1bc6f6 Only set the queue when COMMAND_GET_TIMELINE is available
Android Auto shows a queue button when the queue is not empty.
Apps were able to remove this queue button with the legacy API
by not setting the queue of the session.

After this change, removing `COMMAND_GET_TIMELINE` from the commands
of the media notification controller or the session player sets the
queue in the platform session to null.

#minor-release
Issue: androidx/media#339
PiperOrigin-RevId: 573813558
2023-10-16 08:14:38 -07:00
bachinger
4dc3db4da3 Add MediaSession.Builder().setPeriodicPositionUpdateEnabled()
This allows to disable periodic position updates when building
the session.

#minor-release

PiperOrigin-RevId: 572531837
2023-10-11 04:10:03 -07:00
jbibik
e63be0317f Add multidex Gradle dependency to test-session-current
#minor-release

PiperOrigin-RevId: 571347856
2023-10-06 08:46:11 -07:00
ibaker
e9bf41ca04 Mark test_session_current support app as MultiDexApplication
PiperOrigin-RevId: 570015354
2023-10-02 03:59:36 -07:00
bachinger
99086b4007 Add default implementation of Callback.onSubscribe
The library already maintains the subscribed controllers internally. This
change adds `MediaLibrarySession.getSubscribedControllers(mediaId)` to
access subscribed controllers for a given media ID.

To accept a subscription, `MediaLibraryService.Callback.onSubscribe` is
required to return `RESULT_SUCCESS`. So far, this isn't the case for the
default implementation of the library.

This change implements `Callback.onSubscribe` to conditionally
provide `RESULT_SUCCESS`. The default calls `Callback.onGetItem(mediaId)` to
assess the availability of the media item. If the app retruns `RESULT_SUCCESS`
with a browsable item, the subscription is accepted. If receiving a valid item
fails, the subscription is rejected.

Issue: androidx/media#561
PiperOrigin-RevId: 568925079
2023-09-27 12:19:34 -07:00
tonihei
77ba0292ad Add position interpolation to MediaControllerImplLegacy
Without this, the position won't udpate until the session sends
a new playback state.

PiperOrigin-RevId: 568889286
2023-09-27 10:23:27 -07:00
bachinger
5e05e2ec22 Pass down ControllerInfo from service to session when connecting
With this change, the `ControllerInfo` passed to
`MediaSessionService.onGetSession(ControllerInfo)`
is the same instance that is passed later to all
callback methods of `MediaSession.Callback`.

PiperOrigin-RevId: 568216855
2023-09-25 07:50:12 -07:00
ibaker
1f86a4e48d Remove static initializer block from MediaSessionKeyEventTest
PiperOrigin-RevId: 568149422
2023-09-25 02:02:05 -07:00
bachinger
742410d517 Use proxy controller to maintain platform session and notification
With this change, the notification controller that is connected by
`MediaNotificationManager`, is used as a proxy controller of the
System UI controller. An app can use the proxy at connection time
and during the lifetime of the session for configuration of the
platform session and the media notification on all API levels.

This includes using custom layout and available player and session
commands of the proxy to maintain the platform session (actions,
custom actions, session extras) and the `MediaNotification.Provider`.

The legacy System UI controller is hidden from the public API,
instead the app interacts with the Media3 proxy:

- System UI is hidden from `MediaSession.getConnectedControllers()`.
- Calls from System UI to methods of `MediaSession.Callback`/
  `MediaLibrarySession.Callback` are mapped to the `ControllerInfo`
  of the proxy controller.
- When `getControllerForCurrentRequest()` is called during an operation of
  System UI the proxy `ControllerInfo` is returned.

PiperOrigin-RevId: 567606117
2023-09-22 06:36:22 -07:00
ibaker
fc91ee1d7b Session tests: Add missing CountdownLatch.await()
This helps deflake this test.

PiperOrigin-RevId: 567288892
2023-09-21 06:30:24 -07:00
jbibik
39c1ac7f3a Move setAudioAttributes from ExoPlayer to Player
PiperOrigin-RevId: 566607528
2023-09-19 06:08:37 -07:00
jbibik
0c918d2c47 Fix ErrorProne lint actionable items
PiperOrigin-RevId: 566571653
2023-09-19 03:01:20 -07:00
ibaker
320a45f7d6 Session tests: Log when no controllers are connected
While debugging various session tests failure I found that sometimes
this list was empty (e.g. when a controller had failed to connect, or
hadn't finished connecting yet) - resulting in these methods being
silent no-ops. I think it's basically never expected for there to be no
controllers connected when these methods are invoked, so this logs at
ERROR level to give a clue of what happened when looking at the test
logcat.

PiperOrigin-RevId: 564750969
2023-09-12 09:52:21 -07:00
ibaker
624eb1d7cb Add missing this.session null check in MockMediaLibraryService.
This aligns the equivalent implementation in `MockMediaSessionService`,
and it looks more correct to me - but the tests seem to pass both with
and without this change (and it doesn't seem to affect flakiness
either).

PiperOrigin-RevId: 564689493
2023-09-12 05:33:24 -07:00
ibaker
cf15463b1f Fix parameter comments in MediaBrowser tests
The parameter name was changed in 782a69e38c

PiperOrigin-RevId: 564688136
2023-09-12 05:25:22 -07:00
ibaker
d77c707cd3 Use ISE instead of AssertionError in MockMediaLibraryService
Also pass the full cause instead of just the message.

PiperOrigin-RevId: 564313917
2023-09-11 02:28:38 -07:00
ibaker
06f5324665 Deflake MediaSessionServiceTest.addSessions_removedWhenReleased
While investigating a different test failure on a pending change I
noticed that sometimes the "testAddSessions_removedWhenClose" session
was being released before it could be fully connected - and this
results in a failure like:

```
expected not to contain: androidx.media3.session.MediaSession@50a9ef1
but was                : [androidx.media3.session.MediaSession@50a9ef1, androidx.media3.session.MediaSession@3a6bac]
	at androidx.media3.session.MediaSessionServiceTest.addSessions_removedWhenReleased(MediaSessionServiceTest.java:376)
```

It also shows up in the logs like:

```
MediaController future failed (so we couldn't release it)
...
Caused by: java.lang.SecurityException: Session rejected the connection request.
```

Adding some debug logging revealed that the `session.release` call
posted to the test thread was happening before the call to
`MediaSessionStub.connect` on the main thread (this is triggered deep
in prod media3 session logic).

PiperOrigin-RevId: 563431265
2023-09-07 08:00:25 -07:00
ibaker
b958f451a7 Fix raw type warning in MediaBrowserCompatWithMediaLibraryServiceTest
PiperOrigin-RevId: 563410425
2023-09-07 06:22:56 -07:00
ibaker
956f58f963 Rename session to match addSessions_removedWhenReleased test name
PiperOrigin-RevId: 563132193
2023-09-06 09:46:21 -07:00
ibaker
100af0b2de Fix test_session_current to be consistent with other test packages
This change ensures that a different package is used for
`test_session_current/src/main:support_app` and
`test_session_current/src/androidTest:test_app` - previously they used
the same package which was unusual (and possibly led to some confusing
behaviour).

PiperOrigin-RevId: 563051818
2023-09-06 03:23:44 -07:00
tianyifeng
5a6b88d751 De-flake MediaSessionCompatCallbackWithMediaControllerTest.onStop test
The `controller.prepare()` call can trigger the callback `onPrepare()`, however, this will count down the latch by one before the callback `onStop()` is triggered.

PiperOrigin-RevId: 560988209
2023-08-29 04:28:16 -07:00
tonihei
36084eef05 Split test_session_current instrumentation tests by file
PiperOrigin-RevId: 559089467
2023-08-22 15:50:29 +01:00
tonihei
a00bef9e51 Fix MediaControllerSurfaceSizeChangeTest
There are multiple problems in the test:
 1. The controller must run on the main thread due to the Player
    interface requirement to add surfaces on the thread their
    callbacks will be called on.
 2. This test made assertions about an expected callback that
    aren't true. Setting an anonymous surface will not result in
    a size change callback because the size stays unknown.
    But clearing a surface (even if never set) ensures the returned
    size is guaranteed to be zero.

PiperOrigin-RevId: 559080905
2023-08-22 15:49:08 +01:00
tonihei
fddb09be20 Internal change
PiperOrigin-RevId: 558799565
2023-08-22 15:36:56 +01:00
tianyifeng
15f4ff7487 Remove asserts inside callbacks
PiperOrigin-RevId: 558791481
2023-08-22 15:35:33 +01:00
tonihei
597de8706d Show play button during playback suppression by default
This changes the default logic of shouldShowPlayButton to show a play
button while the playback is temporarily suppressed. This helps to
provide better UI feedback to the fact that playback stopped and
provides a quick way for users to override the suppression and attempt
to restart playback.

Some apps may want to keep the legacy behavior depending on their app's
needs. Hence, we also add a config parameter to set this behavior both
in MediaSession and our default UI components.

Issue: google/ExoPlayer#11213
PiperOrigin-RevId: 557129171
2023-08-15 17:15:38 +01:00
bachinger
17ee5277d5 Only use result.sendError where supported by legacy media library
`MediaLibraryServiceLegacyStub` handles various edge cases by calling
`result.sendError(null)` with the intention to send back an error to
the legacy browser [1].

`MediaBrowserServiceCompat` of the legacy media1 Compat library has an
inner base class `Result` that has a default implementation of
`onErrorSent` that throws an `UnsupportedOperationException` [2].
However, most anonymous inner classes for `Result` created in
`MediaBrowserServiceCompat` do not override `onErrorSent` [3].

Hence Media3 must not call `sendError` in these cases. Instead we call
`sendResult(null)` according to what the default implementation of
the callbacks in `MediaBrowserServiceCompat` do ([4] as an example).

Issue: androidx/media#78
Issue: androidx/media#334

[1] https://github.com/androidx/media/blob/release/libraries/session/src/main/java/androidx/media3/session/MediaLibraryServiceLegacyStub.java#L200
[2] https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:media/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java;l=872
[3] https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:media/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java;l=578-604?q=MediaBrowserServiceCompat&ss=androidx
[4] https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:media/media/src/main/java/androidx/media/MediaBrowserServiceCompat.java;l=1395

PiperOrigin-RevId: 551210137
2023-08-01 14:11:08 +01:00
bachinger
71af48429f Fix flaky test in MediaControllerListenerTest
PiperOrigin-RevId: 550625956
2023-08-01 13:58:49 +01:00
bachinger
a90ec96425 Use MediaUtils.intersect in MediaControllerImplBase
PiperOrigin-RevId: 550566322
2023-08-01 13:54:11 +01:00
Googler
46482e0384 Avoid resetting suppression reason with play/pause on MediaController
Unlike ExoPlayer, when play/pause is called on MediaController, the playback suppression reason is set to default causing a change in it and subsequent callbacks on the Player.Listener.

PiperOrigin-RevId: 548088931
2023-07-20 09:57:51 +01:00
bachinger
ea21d27a69 Add custom layout to the state of the MediaController
This change also marks the buttons of the custom layout as
enabled/disabled according to available commands in the controller.
Accordingly, `CommandButton.Builder.setEnabled(boolean)` is deprecated
because the value is overridden by the library.

Issue: androidx/media#38

#minor-release

PiperOrigin-RevId: 547272588
2023-07-13 15:47:50 +01:00
bachinger
175c64a07b Track controllers that don't await the connection
This removes some stack traces in unit tests when a
`RemoveMediaController` was created with `waitForConnection=false`
in which case the missing controller in the
`MediaControllerProviderService` caused a `NullPointerException`.

PiperOrigin-RevId: 546795181
2023-07-13 15:24:12 +01:00
bachinger
a884186e58 Add android unit test for setting playback speed of a legacy session
PiperOrigin-RevId: 546282819
2023-07-13 15:11:57 +01:00
tonihei
2322462404 Do not trim audio samples by changing their timestamp
MP4 edit lists sometimes ask to start playback between two samples.
If this happens, we currently change the timestamp of the first
sample to zero to trim it (e.g. to display the first frame for a
slightly shorter period of time). However, we can't do this to audio
samples are they have an inherent duration and trimming them this
way is not possible.

#minor-release

PiperOrigin-RevId: 543420218
2023-06-29 22:50:04 +00:00
jbibik
c2d8051662 Cleaner unified PlayerInfo update method in MediaControllerImplBase
`MediaControllerImplBase` has 2 methods for updating listeners about `PlayerInfo` changes - `updatePlayerInfo` (for masking the state) and `onPlayerInfoChanged` (when communicating with the session). There is a set number of listener callbacks related to `PlayerInfo` updates and both methods should go through the same control flow (whether we know that masking will ignore most of them or not).

A unified method `notifyPlayerInfoListenersWithReasons` encapsulates only the shared logic of 2 methods - listeners' callbacks. This ensures that both methods call them in the same order and none are missed out.

PiperOrigin-RevId: 542587879
2023-06-23 16:47:58 +00:00
jbibik
b9cc70d9e2 Fixed spelling across various PlayerInfo *ChangeReason fields
PiperOrigin-RevId: 541892788
2023-06-22 15:23:21 +00:00
bachinger
bd97dd8519 Rollback of 7956c80f73
*** Original commit ***

Rollback of 2a6f893fba

*** Original commit ***

Set video size to 0/0 when video render is disabled

In terms of MCVR wi...

***

PiperOrigin-RevId: 540525069
2023-06-19 16:09:13 +01:00
jbibik
4b5a457790 Notify listeners of error changes when masking in MediaControllerImplBase
Currently, the implementation of `MediaControllerImplBase` differs from `ExoPlayerImpl`. The listeners of the former are notified of player error changes only in `onPlayerInfoChanged` and not `updatePlayerInfo` (masking method). Whereas `ExoPlayerImpl` has one unified method - `updatePlaybackInfo` - which sends the events to all the available listeners.

This change fixes the lack of 2 particular callbacks - `onPlayerErrorChanged` and `onPlayerError`, however, there might be more differences. Ideally, there should be a unified method for oldPlayerInfo/newPlayerInfo comparison-update-notify-listeners flow.

Issue: androidx/media#449

#minor-release

PiperOrigin-RevId: 539961618
2023-06-14 20:32:55 +01:00
jbibik
d9764c18ad Allow playback of MediaItems with LocalConfiguration
When initiated by MediaController, it should be possible for `MediaSession` to pass `MediaItems` to the `Player` if they have `LocalConfiguration`. In such case, it is not required to override `MediaSession.Callback.onAddMediaItems`, because the new current default implementation will handle it.

However, in other cases, MediaItem.toBundle() will continue to strip the LocalConfiguration information.

Issue: androidx/media#282

#minor-release

PiperOrigin-RevId: 537993460
2023-06-06 18:08:17 +00:00
Googler
7956c80f73 Rollback of 2a6f893fba
*** Original commit ***

BEGIN_PUBLIC
Set video size to 0/0 when video render is disabled

In terms of MCVR with a `VideoRendererEventListener`, the video size is set to
0/0 right after `onVideoDisabled()` is called and is set to the actual size as
soon as the video size is known after 'onVideoEnabled()`.

For ExoPlayer and in terms of the `Player` interface, `Player.getVideoSize()`
returns a video size of 0/0 when `Player.getCurrentTracks()` does not support
`C.TRACK_TYPE_VIDEO`. This is ensured by the masking behavior

***

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

Issue: google/ExoPlayer#8046

#minor-release

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

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

#minor-release

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

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

#minor-release

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

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

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

#minor-release

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

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

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

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

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

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

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

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

#minor-release

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

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

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

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

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

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

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

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

PiperOrigin-RevId: 525999084
2023-04-24 11:31:15 +01:00
tonihei
e0bb23d463 Remove unnecessary check for currentMediaItem in legacy session stub
This check was a leftover from when the metadata was generated from
the MediaItem only. Since we moved to the actual MediaMetadata fields,
the check is completely unnecessary and prevents accessing metadata
when the GET_CURRENT_MEDIA_ITEM command is not available.

#minor-release

PiperOrigin-RevId: 524837587
2023-04-17 17:18:57 +01:00
tonihei
1c557e2fd1 Ensure TrackSelectionParameters overrides match existing groups
The overrides specified by a MediaController may not use the exact
same TrackGroup instances as known to the Player because the groups
have been bundled to and from the controller. This bundling may
alter the instance slightly depending on the version used on each
side of the communication and the fields set (e.g. Format.metadata
is not supported for bundling).

This issue can be solved by creating unique track group ids for
each group on the session side before bundling. On the way back,
the groups in the track selection parameters can be mapped backed
to their original instances based on this id.

#minor-release

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

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

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

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

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

#minor-release

Issue: androidx/media#293
PiperOrigin-RevId: 522005562
2023-04-05 11:30:55 +01:00
tonihei
219967c5a3 Allow duplicated MediaItems in a legacy session
MediaItems are not meant to be unique in a playlist. If a legacy
session publishes multiple items that get converted to equal MediaItems,
the current code fails because we look up queue ids in a Map (that
doesn't allow duplicate entries).

Fix this by storing a simple list of items with additional data.

#minor-release

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

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

PiperOrigin-RevId: 519121122
2023-03-30 17:09:28 +00:00