Add suppression reason for unsuitable audio route.

A follow up to stopping speaker playback with a Player decorator from
https://github.com/androidx/media/issues/15.

It looks like we will need to change to using playback suppression to avoid
errors like https://github.com/androidx/media/issues/167, when we don't start
a foreground service.

We may not have this implemented by 1.0, but would like it in the API and it seems to be appropriate.

PiperOrigin-RevId: 478835686
This commit is contained in:
yschimke 2022-10-04 18:09:14 +00:00 committed by Marc Baechinger
parent 253486d4af
commit 278853a2a1
3 changed files with 27 additions and 8 deletions

View File

@ -16,6 +16,9 @@
* Close the Tracing "doSomeWork" block when offload is enabled. * Close the Tracing "doSomeWork" block when offload is enabled.
* Try alternative decoder for Dolby Vision if display does not support it. * Try alternative decoder for Dolby Vision if display does not support it.
([#9794](https://github.com/google/ExoPlayer/issues/9794)). ([#9794](https://github.com/google/ExoPlayer/issues/9794)).
* Add suppression reason for unsuitable audio route and play when ready
change reason for suppressed too long.
([#15](https://github.com/androidx/media/issues/15)).
* Downloads: * Downloads:
* Fix potential infinite loop in `ProgressiveDownloader` caused by * Fix potential infinite loop in `ProgressiveDownloader` caused by
simultaneous download and playback with the same `PriorityTaskManager` simultaneous download and playback with the same `PriorityTaskManager`

View File

@ -791,10 +791,12 @@ package androidx.media3.common {
field public static final int MEDIA_ITEM_TRANSITION_REASON_SEEK = 2; // 0x2 field public static final int MEDIA_ITEM_TRANSITION_REASON_SEEK = 2; // 0x2
field public static final int PLAYBACK_SUPPRESSION_REASON_NONE = 0; // 0x0 field public static final int PLAYBACK_SUPPRESSION_REASON_NONE = 0; // 0x0
field public static final int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1; // 0x1 field public static final int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1; // 0x1
field public static final int PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE = 2; // 0x2
field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY = 3; // 0x3 field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY = 3; // 0x3
field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS = 2; // 0x2 field public static final int PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS = 2; // 0x2
field public static final int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5; // 0x5 field public static final int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5; // 0x5
field public static final int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4; // 0x4 field public static final int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4; // 0x4
field public static final int PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG = 6; // 0x6
field public static final int PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST = 1; // 0x1 field public static final int PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST = 1; // 0x1
field public static final int REPEAT_MODE_ALL = 2; // 0x2 field public static final int REPEAT_MODE_ALL = 2; // 0x2
field public static final int REPEAT_MODE_OFF = 0; // 0x0 field public static final int REPEAT_MODE_OFF = 0; // 0x0
@ -868,10 +870,10 @@ package androidx.media3.common {
@IntDef({androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_SEEK, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.MediaItemTransitionReason { @IntDef({androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_SEEK, androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.MediaItemTransitionReason {
} }
@IntDef({androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlayWhenReadyChangeReason { @IntDef({androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_REMOTE, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM, androidx.media3.common.Player.PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlayWhenReadyChangeReason {
} }
@IntDef({androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlaybackSuppressionReason { @IntDef({androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_NONE, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS, androidx.media3.common.Player.PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.LOCAL_VARIABLE, java.lang.annotation.ElementType.TYPE_USE}) public static @interface Player.PlaybackSuppressionReason {
} }
public static final class Player.PositionInfo { public static final class Player.PositionInfo {

View File

@ -1106,8 +1106,9 @@ public interface Player {
* #PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST}, {@link * #PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST}, {@link
* #PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS}, {@link * #PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS}, {@link
* #PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY}, {@link * #PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY}, {@link
* #PLAY_WHEN_READY_CHANGE_REASON_REMOTE} or {@link * #PLAY_WHEN_READY_CHANGE_REASON_REMOTE}, {@link
* #PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM}. * #PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM} or {@link
* #PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added. // with Kotlin usages from before TYPE_USE was added.
@ -1119,7 +1120,8 @@ public interface Player {
PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_FOCUS_LOSS,
PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY, PLAY_WHEN_READY_CHANGE_REASON_AUDIO_BECOMING_NOISY,
PLAY_WHEN_READY_CHANGE_REASON_REMOTE, PLAY_WHEN_READY_CHANGE_REASON_REMOTE,
PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM,
PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG
}) })
@interface PlayWhenReadyChangeReason {} @interface PlayWhenReadyChangeReason {}
/** Playback has been started or paused by a call to {@link #setPlayWhenReady(boolean)}. */ /** Playback has been started or paused by a call to {@link #setPlayWhenReady(boolean)}. */
@ -1132,11 +1134,17 @@ public interface Player {
int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4; int PLAY_WHEN_READY_CHANGE_REASON_REMOTE = 4;
/** Playback has been paused at the end of a media item. */ /** Playback has been paused at the end of a media item. */
int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5; int PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM = 5;
/**
* Playback has been paused because playback has been {@linkplain #getPlaybackSuppressionReason()
* suppressed} too long.
*/
int PLAY_WHEN_READY_CHANGE_REASON_SUPPRESSED_TOO_LONG = 6;
/** /**
* Reason why playback is suppressed even though {@link #getPlayWhenReady()} is {@code true}. One * Reason why playback is suppressed even though {@link #getPlayWhenReady()} is {@code true}. One
* of {@link #PLAYBACK_SUPPRESSION_REASON_NONE} or {@link * of {@link #PLAYBACK_SUPPRESSION_REASON_NONE}, {@link
* #PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS}. * #PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS} or {@link
* #PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility // @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added. // with Kotlin usages from before TYPE_USE was added.
@ -1145,13 +1153,19 @@ public interface Player {
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({ @IntDef({
PLAYBACK_SUPPRESSION_REASON_NONE, PLAYBACK_SUPPRESSION_REASON_NONE,
PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS,
PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE
}) })
@interface PlaybackSuppressionReason {} @interface PlaybackSuppressionReason {}
/** Playback is not suppressed. */ /** Playback is not suppressed. */
int PLAYBACK_SUPPRESSION_REASON_NONE = 0; int PLAYBACK_SUPPRESSION_REASON_NONE = 0;
/** Playback is suppressed due to transient audio focus loss. */ /** Playback is suppressed due to transient audio focus loss. */
int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1; int PLAYBACK_SUPPRESSION_REASON_TRANSIENT_AUDIO_FOCUS_LOSS = 1;
/**
* Playback is suppressed due to no suitable audio route, such as an attempt to use an internal
* speaker instead of bluetooth headphones on Wear OS.
*/
int PLAYBACK_SUPPRESSION_REASON_UNSUITABLE_AUDIO_ROUTE = 2;
/** /**
* Repeat modes for playback. One of {@link #REPEAT_MODE_OFF}, {@link #REPEAT_MODE_ONE} or {@link * Repeat modes for playback. One of {@link #REPEAT_MODE_OFF}, {@link #REPEAT_MODE_ONE} or {@link