332 Commits

Author SHA1 Message Date
bachinger
0b0d02c3e4 Add isAutomotiveController and isAutoCompanionController
Issue: androidx/media#561
Issue: androidx/media#644
Issue: androidx/media#645
PiperOrigin-RevId: 568948230
2023-09-27 13:45:17 -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
ffd7bb5639 Resolve and dispatch media button events within Media3
Before this change, media button events are routed from `onStartCommand`
of the `MediaSessionService` to  the `MediaSessionCompat`, resolved by
the legacy library to a session command called on
`MediaSessionCompat.Callback` from where the command is delegated back
to the Media3 session.

With this change the keycode is resolved directly to a Media3 command
that is sent to the session through the media notification controller
of the session.

After this change, a playback or custom command sent to the session
from a notification, either as a pending intent (before API 33) or as
a legacy session command, look the same and the caller is the
media notification controller on all API levels.

PiperOrigin-RevId: 568224123
2023-09-25 08:19:33 -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
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
e357d9f218 Don't call MediaSession.Callback.onPostConnect if connecting failed
I spotted that this looked wrong while investigating test various
session test failures. However, changing this logic doesn't seem to
affect the tests so I don't know if the change is an improvement or not.

PiperOrigin-RevId: 566655318
2023-09-19 09:29:40 -07:00
jbibik
39c1ac7f3a Move setAudioAttributes from ExoPlayer to Player
PiperOrigin-RevId: 566607528
2023-09-19 06:08:37 -07:00
christosts
c0e11e0edd Move bitmap loader tests in test
These tests were under androidTest because we needed a functional
BitmapFactory. Robolectric now supports decoding bitmaps so moving them
under tests.

PiperOrigin-RevId: 565181239
2023-09-13 15:40:55 -07:00
bachinger
8c0191d0cb Use media button broadcast receiver above Android 31
This change avoids using a framework API that is deprecated since
API 31 and works around difficulties with this deprecated API on
devices from some manufacturers on API 33/34.

Manually tested with BT headphone connected to:

- Samsung SM-G920F (API 24)
- Pixel (API 28)
- Samsung SM-A515W (API 33)
- Pixel 6 Pro (API 33)

(verified manually with devices and adb output of dumpsys)

Issue: androidx/media#167
PiperOrigin-RevId: 562890206
2023-09-05 14:24:06 -07:00
tianyifeng
32e367fabf Set groupKey for media notification in DefaultMediaNotificationProvider
By doing so, the media notification sent from DefaultMediaNotificationProvider won't be auto-grouped (https://developer.android.com/develop/ui/views/notifications/group#automatic-grouping) with the regular notifications sent from the other places in the app. As the result, when the customer attempts to dismiss the regular notifications (by swiping away), the media notification won't be dismissed as being in the same group.

Issue: androidx/media#549
PiperOrigin-RevId: 561047571
2023-08-29 09:10:12 -07:00
bachinger
6bd3e53e8d Set notification foreground service behaviour starting with API 31
When the foreground service type is set to `mediaPlayiback` this shouldn't
be required. However, some reports from users say that setting the
foreground service behavor fixes some problems on some devices. Setting
it explicitely with this change makes sure users don't have to do that
workaround themselves.

Issue: androidx/media#167
PiperOrigin-RevId: 557608577
2023-08-18 15:09:59 +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
jbibik
dedccc596e Fix PlayerWrapper's creation of VolumeProviderCompat
When hardware buttons are used to control the volume of the remote device, the call propagates to `MediaSessionCompat.setPlaybackToRemote(volumeProviderCompat)`. However, `volumeProviderCompat` was created incorrectly when the new device volume commands were present (COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS and COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS), i.e. with volumeControlType = `VOLUME_CONTROL_FIXED`. This resulted in `VolumeProviderCompat` which doesn't call `onSetVolumeTo` or `onAdjustVolume` and hence doesn't propagate the calls to the `Player`. Instead, it only worked with the deprecated commands which ensured the volumeControlType was `VOLUME_CONTROL_ABSOLUTE`.

This bug was introduced in c71e4bf1ff (1.0 media 3 release) when `PlayerWrapper`'s call to `createVolumeProviderCompat` was mostly rewritten to handle the new commands, but the two if-statements were not amended. Note: this change fixes the bug only for Android 11 and below. For 12 and above, there is a tracking bug for the regression that was introduced: https://issuetracker.google.com/issues/201546605

http://Issue: androidx/media#554

#minor-release

PiperOrigin-RevId: 554966361
2023-08-10 12:12:09 +00: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
a90ec96425 Use MediaUtils.intersect in MediaControllerImplBase
PiperOrigin-RevId: 550566322
2023-08-01 13:54:11 +01:00
bachinger
2c19399d3e Move command button related helper methods to CommandButton
PiperOrigin-RevId: 550558261
2023-08-01 13:53:09 +01:00
bachinger
d658de5944 Mark media notification controller and filter command buttons
The `MediaNotificationManager` registers an internal controller
to each session. This change marks this controller through its
connection hints and provides an API for apps to hide
implementation details of the marking.

Issue: androidx/media#389
PiperOrigin-RevId: 549712768
2023-08-01 13:44:12 +01:00
tonihei
8064c6df83 Declare foreground service type for DownloadService
This ensures the DownloadService stays functional on Android 14
where defining this type is required. On Android 14 and above,
the app also needs to define the DATA_SYNC permission, which is
added to the demo app as well. In the future, this service type
will no longer be supported and DownloadService needs to be
rewritten with another background scheduling framework.

Issue: google/ExoPlayer#11239
PiperOrigin-RevId: 548994842
2023-07-20 10:23:56 +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
siroberts
ab904bde2d Prevent the creation of CommandButtons without commands.
The setPlayerCommand and setSessionCommand builder methods contain assertions to ensure that at most one of these fields is set, but this left it possible to create a command button with no command by calling build on an empty builder.

PiperOrigin-RevId: 547488248
2023-07-13 15:56:43 +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
ibaker
eed0e42ff8 Remove javadoc @link from non-javadoc comments
Also update type names to match the current names for these types.

PiperOrigin-RevId: 546884049
2023-07-13 15:32:21 +01:00
ibaker
5e96d355e1 Suppress NewApi lint warning on <vector> usage in drawables
PiperOrigin-RevId: 545207308
2023-07-05 09:08:51 +00:00
ibaker
dc311fd0ca Remove IfAny suffix from @Nullable IntDef locals in MCImplBase
We use `@Nullable` for IntDefs in other places and don't use this suffix
elsewhere, so I don't think we need it here either.

PiperOrigin-RevId: 543687285
2023-06-29 22:57:38 +00: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
b8ac5b4210 Order MediaControllerImplBase listener callbacks as in ExoPlayerImpl
The callbacks for `PlayerInfo` changes are currently in both `MediaControllerImplBase.updatePlayerInfo` (masking) and `MediaControllerImplBase.onPlayerInfoChanged`. But the order was different between them both and `ExoPlayerImpl.updatePlaybackInfo` which they are trying to mimic.

#minor-release

PiperOrigin-RevId: 542519070
2023-06-22 15:45:21 +00:00
tofunmi
be38670391 Transformer: Decode image in sRGB
The effects pipeline must receive images in the sRGB colorspace due to the color transfers applied in the shaders. Currently the burden to making sure images are in the right colorspaces falls onto apps. This CL ensures that this is not the case anymore.

PiperOrigin-RevId: 542323613
2023-06-22 15:41:55 +00:00
jbibik
b9cc70d9e2 Fixed spelling across various PlayerInfo *ChangeReason fields
PiperOrigin-RevId: 541892788
2023-06-22 15:23:21 +00:00
jbibik
501da109ce Default RepeatMode for conversion is NONE/OFF
Current behaviour causes an app to crash if it receives an unrecognized repeat mode send over the wire. In order to avoid the crash, a sensible default had to be chosen.

For `Player.RepeatMode`, it is `Player.REPEAT_MODE_OFF`, which is the same value we use as default when unbundling `PlayerInfo`.

For `PlaybackStateCompat.RepeatMode`, it is `PlaybackStateCompat.REPEAT_MODE_NONE`, which is what we use in the no-arg `LegacyPlayerInfo` constructor.

Issue: androidx/media#448

#minor-release

PiperOrigin-RevId: 540563792
2023-06-19 16:13:39 +01:00
tonihei
51fb72b00d Replace deprecated NullableType from checkerframework with our own one
The existing NullableType has been deprecated 5 years ago and causes
crashes in Kotlin apps because Kotlin doesn't recognize this annotation
as a nullable type annotation.

While we can't align on a single @Nullable annotation yet, we can at
least replace this one by JSR305's @Nonnull(MAYBE) as it fulfils all
requirements, including full Kotlin compatiblity. To avoid the
cumbersome name, we can redefine it as our own @NullableType
annotation. (We can't use @Nullable to avoid name clashes with the main
@Nullable annotation from AndroidX)

Issue: google/ExoPlayer#6792
PiperOrigin-RevId: 540497469
2023-06-19 16:08:20 +01:00
siroberts
cf21add916 Add missing checkNotNull to bitmapLoader.
#minor-release

PiperOrigin-RevId: 540309118
2023-06-14 20:47:04 +01:00
bachinger
3d674fa2f3 Implement equals/hashCode for CommandButton
#minor-release

PiperOrigin-RevId: 540274932
2023-06-14 20:45:36 +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
tianyifeng
2e2f19351f Add seekPrev and seekNext buttons on the default compact notification
This change is for Android 12 and below, where the buttons are derived from the actions added with the notification. From Android 13 (https://developer.android.com/about/versions/13/behavior-changes-13#playback-controls), the system derives media controls from `PlaybackState` actions.

When adding the actions onto the notification, the logic will iterate all the command buttons. The `COMMAND_KEY_CONPACT_VIEW_INDEX` extra will be checked for each button. If that extra is set for the three buttons on the compact view, then the customized buttons and their order will be used. Otherwise, the compact view will be "seekPrev" (if any), "play/pause" (if any), "seekNext" (if any) buttons (in such order).

Issue: androidx/media#410
PiperOrigin-RevId: 538797874
2023-06-09 13:54:13 +00: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
ibaker
fa990714fe Remove exoplayer2-specific parts from media3-only files
PiperOrigin-RevId: 537038419
2023-06-02 09:19:32 +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
1fa790348e Untangle PlayerInfo/PlaybackInfo updates
The methods in ExoPlayerImpl and MediaControllerImplBase that determine
the new PlayerInfo/PlaybackInfo currently have a hard-to-reason-about
setup where the method generating the new info accesses other methods
that rely on the existing class field instead of working with the
passed in PlayerInfo/PlaybackInfo. This prevents reuse of the util
methods (e.g. for replaceMediaItems) because they access potentially
stale state.

This change untangles these methods a bit by making the util methods
either static or at least ensure that they don't rely on existing
class fields of PlayerInfo/PlaybackInfo. Overall, the change is a
complete no-op.

#minor-release

PiperOrigin-RevId: 534036633
2023-05-24 15:39:31 +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
ibaker
485517f34d Upgrade to Gradle 8.0 and Android Gradle Plugin 8.0.1
This change was auto-generated by the Android Studio Upgrade Assistant.

Issue: androidx/media#409
PiperOrigin-RevId: 533467455
2023-05-19 17:24:28 +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
d5f9cf4f19 Add singleVariant publishing config to all published gradle files
Docs:
* https://developer.android.com/build/publish-library/configure-pub-variants#single-pub-var
* https://developer.android.com/reference/tools/gradle-api/8.0/com/android/build/api/dsl/PublishingOptions

This resolves the following warning from Android Gradle Plugin 7.2.2 and
helps unblock the upgrade to AGP 8.0.1:

> Software Components will not be created automatically for Maven
> publishing from Android Gradle Plugin 8.0. To opt-in to the future
> behavior, set the Gradle property
> `android.disableAutomaticComponentCreation=true` in the
> `gradle.properties` file or use the new publishing DSL.
>
> Affected Modules: `lib-cast`, `lib-common`, `lib-container`,
> `lib-database`, `lib-datasource`, `lib-datasource-cronet`,
> `lib-datasource-okhttp`, `lib-datasource-rtmp`, `lib-decoder`,
> `lib-effect`, `lib-exoplayer`, `lib-exoplayer-all (legacy)`,
> `lib-exoplayer-dash`, `lib-exoplayer-hls`, `lib-exoplayer-ima`,
> `lib-exoplayer-rtsp`, `lib-exoplayer-smoothstreaming`,
> `lib-exoplayer-workmanager`, `lib-extractor`, `lib-media2 (legacy)`,
> `lib-mediasession (legacy)`, `lib-muxer`, `lib-session`,
> `lib-transformer`, `lib-ui`, `lib-ui-leanback`, `test-utils`,
> `test-utils-robolectric`

Issue: androidx/media#409
PiperOrigin-RevId: 533464133
2023-05-19 17:22:21 +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
ibaker
fe19dc421d Add logging where we were swallowing failed futures in media3.session
This may not be completely exhaustive, but it's better than before!

#minor-release

PiperOrigin-RevId: 533457167
2023-05-19 17:17:23 +01:00
tonihei
79657692e4 Remove unnecessary warning suppression
PiperOrigin-RevId: 532114601
2023-05-16 09:53:35 +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