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
This commit is contained in:
jbibik 2023-04-13 13:28:33 +01:00 committed by Rohit Singh
parent e033dbac03
commit c71e4bf1ff
37 changed files with 1273 additions and 221 deletions

View File

@ -42,6 +42,12 @@
([#293](https://github.com/androidx/media/issues/293)).
* Fix bug where calling `MediaSession.setPlayer` doesn't update the
available commands.
* Deprecate 4 volume-controlling methods in `Player` and add overloaded
methods which allow users to specify volume flags:
* `void setDeviceVolume(int, int)`
* `void increaseDeviceVolume(int)`
* `void decreaseDeviceVolume(int)`
* `void setDeviceMuted(boolean, int)`
* Audio:
* Fix bug where some playbacks fail when tunneling is enabled and
`AudioProcessors` are active, e.g. for gapless trimming

40
api.txt
View File

@ -127,6 +127,11 @@ package androidx.media3.common {
field public static final int USAGE_VOICE_COMMUNICATION = 2; // 0x2
field public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3; // 0x3
field public static final java.util.UUID UUID_NIL;
field public static final int VOLUME_FLAG_ALLOW_RINGER_MODES = 2; // 0x2
field public static final int VOLUME_FLAG_PLAY_SOUND = 4; // 0x4
field public static final int VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
field public static final int VOLUME_FLAG_SHOW_UI = 1; // 0x1
field public static final int VOLUME_FLAG_VIBRATE = 16; // 0x10
field public static final int WAKE_MODE_LOCAL = 1; // 0x1
field public static final int WAKE_MODE_NETWORK = 2; // 0x2
field public static final int WAKE_MODE_NONE = 0; // 0x0
@ -163,6 +168,9 @@ package androidx.media3.common {
@IntDef(open=true, value={androidx.media3.common.C.TRACK_TYPE_UNKNOWN, androidx.media3.common.C.TRACK_TYPE_DEFAULT, androidx.media3.common.C.TRACK_TYPE_AUDIO, androidx.media3.common.C.TRACK_TYPE_VIDEO, androidx.media3.common.C.TRACK_TYPE_TEXT, androidx.media3.common.C.TRACK_TYPE_IMAGE, androidx.media3.common.C.TRACK_TYPE_METADATA, androidx.media3.common.C.TRACK_TYPE_CAMERA_MOTION, androidx.media3.common.C.TRACK_TYPE_NONE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public static @interface C.TrackType {
}
@IntDef(flag=true, value={androidx.media3.common.C.VOLUME_FLAG_SHOW_UI, androidx.media3.common.C.VOLUME_FLAG_ALLOW_RINGER_MODES, androidx.media3.common.C.VOLUME_FLAG_PLAY_SOUND, androidx.media3.common.C.VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE, androidx.media3.common.C.VOLUME_FLAG_VIBRATE}) @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE_USE}) public static @interface C.VolumeFlags {
}
@IntDef({androidx.media3.common.C.WAKE_MODE_NONE, androidx.media3.common.C.WAKE_MODE_LOCAL, androidx.media3.common.C.WAKE_MODE_NETWORK}) @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 C.WakeMode {
}
@ -666,7 +674,8 @@ package androidx.media3.common {
method public void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder);
method public void clearVideoSurfaceView(@Nullable android.view.SurfaceView);
method public void clearVideoTextureView(@Nullable android.view.TextureView);
method public void decreaseDeviceVolume();
method @Deprecated public void decreaseDeviceVolume();
method public void decreaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int);
method public android.os.Looper getApplicationLooper();
method public androidx.media3.common.AudioAttributes getAudioAttributes();
method public androidx.media3.common.Player.Commands getAvailableCommands();
@ -710,7 +719,8 @@ package androidx.media3.common {
method @FloatRange(from=0, to=1.0) public float getVolume();
method public boolean hasNextMediaItem();
method public boolean hasPreviousMediaItem();
method public void increaseDeviceVolume();
method @Deprecated public void increaseDeviceVolume();
method public void increaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int);
method public boolean isCommandAvailable(@androidx.media3.common.Player.Command int);
method public boolean isCurrentMediaItemDynamic();
method public boolean isCurrentMediaItemLive();
@ -738,8 +748,10 @@ package androidx.media3.common {
method public void seekToNextMediaItem();
method public void seekToPrevious();
method public void seekToPreviousMediaItem();
method public void setDeviceMuted(boolean);
method public void setDeviceVolume(@IntRange(from=0) int);
method @Deprecated public void setDeviceMuted(boolean);
method public void setDeviceMuted(boolean, @androidx.media3.common.C.VolumeFlags int);
method @Deprecated public void setDeviceVolume(@IntRange(from=0) int);
method public void setDeviceVolume(@IntRange(from=0) int, int);
method public void setMediaItem(androidx.media3.common.MediaItem);
method public void setMediaItem(androidx.media3.common.MediaItem, long);
method public void setMediaItem(androidx.media3.common.MediaItem, boolean);
@ -759,7 +771,8 @@ package androidx.media3.common {
method public void setVideoTextureView(@Nullable android.view.TextureView);
method public void setVolume(@FloatRange(from=0, to=1.0) float);
method public void stop();
field public static final int COMMAND_ADJUST_DEVICE_VOLUME = 26; // 0x1a
field @Deprecated public static final int COMMAND_ADJUST_DEVICE_VOLUME = 26; // 0x1a
field public static final int COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS = 34; // 0x22
field public static final int COMMAND_CHANGE_MEDIA_ITEMS = 20; // 0x14
field public static final int COMMAND_GET_AUDIO_ATTRIBUTES = 21; // 0x15
field public static final int COMMAND_GET_CURRENT_MEDIA_ITEM = 16; // 0x10
@ -783,7 +796,8 @@ package androidx.media3.common {
field public static final int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 8; // 0x8
field public static final int COMMAND_SEEK_TO_PREVIOUS = 7; // 0x7
field public static final int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 6; // 0x6
field public static final int COMMAND_SET_DEVICE_VOLUME = 25; // 0x19
field @Deprecated public static final int COMMAND_SET_DEVICE_VOLUME = 25; // 0x19
field public static final int COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS = 33; // 0x21
field public static final int COMMAND_SET_MEDIA_ITEM = 31; // 0x1f
field @Deprecated public static final int COMMAND_SET_MEDIA_ITEMS_METADATA = 19; // 0x13
field public static final int COMMAND_SET_PLAYLIST_METADATA = 19; // 0x13
@ -855,7 +869,7 @@ package androidx.media3.common {
field public static final int TIMELINE_CHANGE_REASON_SOURCE_UPDATE = 1; // 0x1
}
@IntDef({androidx.media3.common.Player.COMMAND_INVALID, androidx.media3.common.Player.COMMAND_PLAY_PAUSE, androidx.media3.common.Player.COMMAND_PREPARE, androidx.media3.common.Player.COMMAND_STOP, androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION, androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT, androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_BACK, androidx.media3.common.Player.COMMAND_SEEK_FORWARD, androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH, androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE, androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE, androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_GET_TIMELINE, androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_GET_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_PLAYLIST_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS, androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES, androidx.media3.common.Player.COMMAND_GET_VOLUME, androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE, androidx.media3.common.Player.COMMAND_GET_TEXT, androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS, androidx.media3.common.Player.COMMAND_GET_TRACKS, androidx.media3.common.Player.COMMAND_RELEASE}) @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.Command {
@IntDef({androidx.media3.common.Player.COMMAND_INVALID, androidx.media3.common.Player.COMMAND_PLAY_PAUSE, androidx.media3.common.Player.COMMAND_PREPARE, androidx.media3.common.Player.COMMAND_STOP, androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION, androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT, androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_SEEK_BACK, androidx.media3.common.Player.COMMAND_SEEK_FORWARD, androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH, androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE, androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE, androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_GET_TIMELINE, androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_GET_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEMS_METADATA, androidx.media3.common.Player.COMMAND_SET_PLAYLIST_METADATA, androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM, androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS, androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES, androidx.media3.common.Player.COMMAND_GET_VOLUME, androidx.media3.common.Player.COMMAND_GET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME, androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS, androidx.media3.common.Player.COMMAND_SET_VIDEO_SURFACE, androidx.media3.common.Player.COMMAND_GET_TEXT, androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS, androidx.media3.common.Player.COMMAND_GET_TRACKS, androidx.media3.common.Player.COMMAND_RELEASE}) @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.Command {
}
public static final class Player.Commands {
@ -1499,7 +1513,8 @@ package androidx.media3.session {
method public final void clearVideoSurfaceHolder(@Nullable android.view.SurfaceHolder);
method public final void clearVideoSurfaceView(@Nullable android.view.SurfaceView);
method public final void clearVideoTextureView(@Nullable android.view.TextureView);
method public final void decreaseDeviceVolume();
method @Deprecated public final void decreaseDeviceVolume();
method public final void decreaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int);
method public final android.os.Looper getApplicationLooper();
method public final androidx.media3.common.AudioAttributes getAudioAttributes();
method public final androidx.media3.common.Player.Commands getAvailableCommands();
@ -1546,7 +1561,8 @@ package androidx.media3.session {
method @FloatRange(from=0, to=1) public final float getVolume();
method public final boolean hasNextMediaItem();
method public final boolean hasPreviousMediaItem();
method public final void increaseDeviceVolume();
method @Deprecated public final void increaseDeviceVolume();
method public final void increaseDeviceVolume(@androidx.media3.common.C.VolumeFlags int);
method public final boolean isCommandAvailable(@androidx.media3.common.Player.Command int);
method public final boolean isConnected();
method public final boolean isCurrentMediaItemDynamic();
@ -1579,8 +1595,10 @@ package androidx.media3.session {
method public final void seekToPrevious();
method public final void seekToPreviousMediaItem();
method public final com.google.common.util.concurrent.ListenableFuture<androidx.media3.session.SessionResult> sendCustomCommand(androidx.media3.session.SessionCommand, android.os.Bundle);
method public final void setDeviceMuted(boolean);
method public final void setDeviceVolume(@IntRange(from=0) int);
method @Deprecated public final void setDeviceMuted(boolean);
method public final void setDeviceMuted(boolean, @androidx.media3.common.C.VolumeFlags int);
method @Deprecated public final void setDeviceVolume(@IntRange(from=0) int);
method public final void setDeviceVolume(@IntRange(from=0) int, @androidx.media3.common.C.VolumeFlags int);
method public final void setMediaItem(androidx.media3.common.MediaItem);
method public final void setMediaItem(androidx.media3.common.MediaItem, long);
method public final void setMediaItem(androidx.media3.common.MediaItem, boolean);

View File

@ -14,7 +14,7 @@
apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle"
dependencies {
api 'com.google.android.gms:play-services-cast-framework:21.2.0'
api 'com.google.android.gms:play-services-cast-framework:21.3.0'
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
implementation project(modulePrefix + 'lib-common')
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion

View File

@ -755,22 +755,50 @@ public final class CastPlayer extends BasePlayer {
return false;
}
/** This method is not supported and does nothing. */
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {}
/** This method is not supported and does nothing. */
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {}
/** This method is not supported and does nothing. */
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {}
/** This method is not supported and does nothing. */
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {}
/** This method is not supported and does nothing. */
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {}
// Internal methods.
// Call deprecated callbacks.

View File

@ -409,6 +409,37 @@ public final class C {
/** The default stream type used by audio renderers. Equal to {@link #STREAM_TYPE_MUSIC}. */
@UnstableApi public static final int STREAM_TYPE_DEFAULT = STREAM_TYPE_MUSIC;
/**
* Volume flags to be used when setting or adjusting device volume. The value can be either 0 or a
* combination of the following flags: {@link #VOLUME_FLAG_SHOW_UI}, {@link
* #VOLUME_FLAG_ALLOW_RINGER_MODES}, {@link #VOLUME_FLAG_PLAY_SOUND}, {@link
* #VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE}, {@link #VOLUME_FLAG_VIBRATE}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({TYPE_USE})
@IntDef(
flag = true,
value = {
VOLUME_FLAG_SHOW_UI,
VOLUME_FLAG_ALLOW_RINGER_MODES,
VOLUME_FLAG_PLAY_SOUND,
VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE,
VOLUME_FLAG_VIBRATE,
})
public @interface VolumeFlags {}
/** See {@link AudioManager#FLAG_SHOW_UI}. */
public static final int VOLUME_FLAG_SHOW_UI = AudioManager.FLAG_SHOW_UI;
/** See {@link AudioManager#FLAG_ALLOW_RINGER_MODES}. */
public static final int VOLUME_FLAG_ALLOW_RINGER_MODES = AudioManager.FLAG_ALLOW_RINGER_MODES;
/** See {@link AudioManager#FLAG_PLAY_SOUND}. */
public static final int VOLUME_FLAG_PLAY_SOUND = AudioManager.FLAG_PLAY_SOUND;
/** See {@link AudioManager#FLAG_REMOVE_SOUND_AND_VIBRATE}. */
public static final int VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE =
AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE;
/** See {@link AudioManager#FLAG_VIBRATE}. */
public static final int VOLUME_FLAG_VIBRATE = AudioManager.FLAG_VIBRATE;
/**
* Content types for audio attributes. One of:
*

View File

@ -846,30 +846,66 @@ public class ForwardingPlayer implements Player {
return player.isDeviceMuted();
}
/** Calls {@link Player#setDeviceVolume(int)} on the delegate. */
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
player.setDeviceVolume(volume);
}
/** Calls {@link Player#increaseDeviceVolume()} on the delegate. */
/** Calls {@link Player#setDeviceVolume(int, int)} on the delegate. */
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
player.setDeviceVolume(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
player.increaseDeviceVolume();
}
/** Calls {@link Player#decreaseDeviceVolume()} on the delegate. */
/** Calls {@link Player#increaseDeviceVolume(int)} on the delegate. */
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
player.increaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
player.decreaseDeviceVolume();
}
/** Calls {@link Player#setDeviceMuted(boolean)} on the delegate. */
/** Calls {@link Player#decreaseDeviceVolume(int)} on the delegate. */
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
player.decreaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
player.setDeviceMuted(muted);
}
/** Calls {@link Player#setDeviceMuted(boolean, int)} on the delegate. */
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
player.setDeviceMuted(muted, flags);
}
/** Returns the {@link Player} to which operations are forwarded. */
public Player getWrappedPlayer() {
return player;

View File

@ -380,7 +380,9 @@ public interface Player {
COMMAND_GET_DEVICE_VOLUME,
COMMAND_SET_VOLUME,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_SET_VIDEO_SURFACE,
COMMAND_GET_TEXT,
COMMAND_SET_TRACK_SELECTION_PARAMETERS,
@ -1437,7 +1439,9 @@ public interface Player {
* <li>{@link #COMMAND_GET_DEVICE_VOLUME}
* <li>{@link #COMMAND_SET_VOLUME}
* <li>{@link #COMMAND_SET_DEVICE_VOLUME}
* <li>{@link #COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS}
* <li>{@link #COMMAND_ADJUST_DEVICE_VOLUME}
* <li>{@link #COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS}
* <li>{@link #COMMAND_SET_VIDEO_SURFACE}
* <li>{@link #COMMAND_GET_TEXT}
* <li>{@link #COMMAND_SET_TRACK_SELECTION_PARAMETERS}
@ -1481,7 +1485,9 @@ public interface Player {
COMMAND_GET_DEVICE_VOLUME,
COMMAND_SET_VOLUME,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_SET_VIDEO_SURFACE,
COMMAND_GET_TEXT,
COMMAND_SET_TRACK_SELECTION_PARAMETERS,
@ -1788,27 +1794,36 @@ public interface Player {
* #isCommandAvailable(int) available}.
*/
int COMMAND_SET_VOLUME = 24;
/**
* Command to set the device volume.
*
* <p>The {@link #setDeviceVolume(int)} method must only be called if this command is {@linkplain
* #isCommandAvailable(int) available}.
*/
int COMMAND_SET_DEVICE_VOLUME = 25;
/**
* Command to increase and decrease the device volume and mute it.
* @deprecated Use {@link #COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS} instead.
*/
@Deprecated int COMMAND_SET_DEVICE_VOLUME = 25;
/**
* Command to set the device volume with volume flags.
*
* <p>The {@link #setDeviceVolume(int, int)} method must only be called if this command is
* {@linkplain #isCommandAvailable(int) available}.
*/
int COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS = 33;
/**
* @deprecated Use {@link #COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} instead.
*/
@Deprecated int COMMAND_ADJUST_DEVICE_VOLUME = 26;
/**
* Command to increase and decrease the device volume and mute it with volume flags.
*
* <p>The following methods must only be called if this command is {@linkplain
* #isCommandAvailable(int) available}:
*
* <ul>
* <li>{@link #increaseDeviceVolume()}
* <li>{@link #decreaseDeviceVolume()}
* <li>{@link #setDeviceMuted(boolean)}
* <li>{@link #increaseDeviceVolume(int)}
* <li>{@link #decreaseDeviceVolume(int)}
* <li>{@link #setDeviceMuted(boolean, int)}
* </ul>
*/
int COMMAND_ADJUST_DEVICE_VOLUME = 26;
int COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS = 34;
/**
* Command to set and clear the surface on which to render the video.
@ -3095,36 +3110,68 @@ public interface Player {
boolean isDeviceMuted();
/**
* Sets the volume of the device.
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
void setDeviceVolume(@IntRange(from = 0) int volume);
/**
* Sets the volume of the device with volume flags.
*
* <p>This method must only be called if {@link #COMMAND_SET_DEVICE_VOLUME} is {@linkplain
* #getAvailableCommands() available}.
* <p>This method must only be called if {@link #COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS} is
* {@linkplain #getAvailableCommands() available}.
*
* @param volume The volume to set.
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
void setDeviceVolume(@IntRange(from = 0) int volume);
void setDeviceVolume(@IntRange(from = 0) int volume, int flags);
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
void increaseDeviceVolume();
/**
* Increases the volume of the device.
*
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME} is {@linkplain
* #getAvailableCommands() available}.
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is
* {@linkplain #getAvailableCommands() available}.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
void increaseDeviceVolume();
void increaseDeviceVolume(@C.VolumeFlags int flags);
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
void decreaseDeviceVolume();
/**
* Decreases the volume of the device.
*
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME} is {@linkplain
* #getAvailableCommands() available}.
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is
* {@linkplain #getAvailableCommands() available}.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
void decreaseDeviceVolume();
void decreaseDeviceVolume(@C.VolumeFlags int flags);
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
void setDeviceMuted(boolean muted);
/**
* Sets the mute state of the device.
*
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME} is {@linkplain
* #getAvailableCommands() available}.
* <p>This method must only be called if {@link #COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is
* {@linkplain #getAvailableCommands() available}.
*
* @param muted Whether to set the device to be muted or not
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
void setDeviceMuted(boolean muted);
void setDeviceMuted(boolean muted, @C.VolumeFlags int flags);
}

View File

@ -2661,6 +2661,10 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return state.isDeviceMuted;
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public final void setDeviceVolume(int volume) {
verifyApplicationThreadAndInitState();
@ -2670,10 +2674,27 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleSetDeviceVolume(volume),
/* pendingOperation= */ handleSetDeviceVolume(volume, C.VOLUME_FLAG_SHOW_UI),
/* placeholderStateSupplier= */ () -> state.buildUpon().setDeviceVolume(volume).build());
}
@Override
public final void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
verifyApplicationThreadAndInitState();
// Use a local copy to ensure the lambda below uses the current state value.
State state = this.state;
if (!shouldHandleCommand(Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleSetDeviceVolume(volume, flags),
/* placeholderStateSupplier= */ () -> state.buildUpon().setDeviceVolume(volume).build());
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public final void increaseDeviceVolume() {
verifyApplicationThreadAndInitState();
@ -2683,11 +2704,29 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleIncreaseDeviceVolume(),
/* pendingOperation= */ handleIncreaseDeviceVolume(C.VOLUME_FLAG_SHOW_UI),
/* placeholderStateSupplier= */ () ->
state.buildUpon().setDeviceVolume(state.deviceVolume + 1).build());
}
@Override
public final void increaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThreadAndInitState();
// Use a local copy to ensure the lambda below uses the current state value.
State state = this.state;
if (!shouldHandleCommand(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleIncreaseDeviceVolume(flags),
/* placeholderStateSupplier= */ () ->
state.buildUpon().setDeviceVolume(state.deviceVolume + 1).build());
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public final void decreaseDeviceVolume() {
verifyApplicationThreadAndInitState();
@ -2697,11 +2736,29 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleDecreaseDeviceVolume(),
/* pendingOperation= */ handleDecreaseDeviceVolume(C.VOLUME_FLAG_SHOW_UI),
/* placeholderStateSupplier= */ () ->
state.buildUpon().setDeviceVolume(max(0, state.deviceVolume - 1)).build());
}
@Override
public final void decreaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThreadAndInitState();
// Use a local copy to ensure the lambda below uses the current state value.
State state = this.state;
if (!shouldHandleCommand(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleDecreaseDeviceVolume(flags),
/* placeholderStateSupplier= */ () ->
state.buildUpon().setDeviceVolume(max(0, state.deviceVolume - 1)).build());
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public final void setDeviceMuted(boolean muted) {
verifyApplicationThreadAndInitState();
@ -2711,7 +2768,20 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleSetDeviceMuted(muted),
/* pendingOperation= */ handleSetDeviceMuted(muted, C.VOLUME_FLAG_SHOW_UI),
/* placeholderStateSupplier= */ () -> state.buildUpon().setIsDeviceMuted(muted).build());
}
@Override
public final void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
verifyApplicationThreadAndInitState();
// Use a local copy to ensure the lambda below uses the current state value.
State state = this.state;
if (!shouldHandleCommand(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
updateStateForPendingOperation(
/* pendingOperation= */ handleSetDeviceMuted(muted, flags),
/* placeholderStateSupplier= */ () -> state.buildUpon().setIsDeviceMuted(muted).build());
}
@ -2928,60 +2998,78 @@ public abstract class SimpleBasePlayer extends BasePlayer {
}
/**
* Handles calls to {@link Player#setDeviceVolume}.
* Handles calls to {@link Player#setDeviceVolume(int)} and {@link Player#setDeviceVolume(int,
* int)}.
*
* <p>Will only be called if {@link Player#COMMAND_SET_DEVICE_VOLUME} is available.
* <p>Will only be called if {@link Player#COMMAND_SET_DEVICE_VOLUME} or {@link
* Player#COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS} is available.
*
* @param deviceVolume The requested device volume.
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleSetDeviceVolume(@IntRange(from = 0) int deviceVolume) {
throw new IllegalStateException("Missing implementation to handle COMMAND_SET_DEVICE_VOLUME");
}
/**
* Handles calls to {@link Player#increaseDeviceVolume()}.
*
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available.
*
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleIncreaseDeviceVolume() {
protected ListenableFuture<?> handleSetDeviceVolume(
@IntRange(from = 0) int deviceVolume, int flags) {
throw new IllegalStateException(
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME");
"Missing implementation to handle COMMAND_SET_DEVICE_VOLUME or"
+ " COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS");
}
/**
* Handles calls to {@link Player#decreaseDeviceVolume()}.
* Handles calls to {@link Player#increaseDeviceVolume()} and {@link
* Player#increaseDeviceVolume(int)}.
*
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available.
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} or {@link
* Player#COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is available.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleDecreaseDeviceVolume() {
protected ListenableFuture<?> handleIncreaseDeviceVolume(@C.VolumeFlags int flags) {
throw new IllegalStateException(
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME");
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME or"
+ " COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS");
}
/**
* Handles calls to {@link Player#setDeviceMuted}.
* Handles calls to {@link Player#decreaseDeviceVolume()} and {@link
* Player#decreaseDeviceVolume(int)}.
*
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} is available.
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} or {@link
* Player#COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS} is available.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleDecreaseDeviceVolume(@C.VolumeFlags int flags) {
throw new IllegalStateException(
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME or"
+ " COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS");
}
/**
* Handles calls to {@link Player#setDeviceMuted(boolean)} and {@link
* Player#setDeviceMuted(boolean, int)}.
*
* <p>Will only be called if {@link Player#COMMAND_ADJUST_DEVICE_VOLUME} or {@link
* Player#COMMAND_ADJUST_DEVICE_VOLUME} is available.
*
* @param muted Whether the device was requested to be muted.
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
* @return A {@link ListenableFuture} indicating the completion of all immediate {@link State}
* changes caused by this call.
*/
@ForOverride
protected ListenableFuture<?> handleSetDeviceMuted(boolean muted) {
protected ListenableFuture<?> handleSetDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
throw new IllegalStateException(
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME");
"Missing implementation to handle COMMAND_ADJUST_DEVICE_VOLUME or"
+ " COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS");
}
/**

View File

@ -3190,6 +3190,8 @@ public class SimpleBasePlayerTest {
.build();
// Set a different one to the one requested to ensure the updated state is used.
State updatedState = state.buildUpon().setDeviceVolume(6).build();
AtomicInteger flagsFromHandlerRef = new AtomicInteger();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
private State playerState = state;
@ -3200,18 +3202,20 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceVolume(int volume) {
protected ListenableFuture<?> handleSetDeviceVolume(int volume, int flags) {
playerState = updatedState;
flagsFromHandlerRef.set(flags);
return Futures.immediateVoidFuture();
}
};
Listener listener = mock(Listener.class);
player.addListener(listener);
player.setDeviceVolume(3);
player.setDeviceVolume(3, volumeFlags);
assertThat(player.getDeviceVolume()).isEqualTo(6);
verify(listener).onDeviceVolumeChanged(6, /* muted= */ false);
assertThat(flagsFromHandlerRef.get()).isEqualTo(volumeFlags);
verifyNoMoreInteractions(listener);
}
@ -3222,6 +3226,8 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(new Commands.Builder().addAllCommands().build())
.build();
// Set a new volume to see a difference between the placeholder and new state.
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
AtomicInteger flagsFromHandlerRef = new AtomicInteger();
State updatedState = state.buildUpon().setDeviceVolume(6).build();
SettableFuture<?> future = SettableFuture.create();
SimpleBasePlayer player =
@ -3232,18 +3238,20 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceVolume(int volume) {
protected ListenableFuture<?> handleSetDeviceVolume(int volume, int flags) {
flagsFromHandlerRef.set(flags);
return future;
}
};
Listener listener = mock(Listener.class);
player.addListener(listener);
player.setDeviceVolume(3);
player.setDeviceVolume(3, volumeFlags);
// Verify placeholder state and listener calls.
assertThat(player.getDeviceVolume()).isEqualTo(3);
verify(listener).onDeviceVolumeChanged(3, /* muted= */ false);
assertThat(flagsFromHandlerRef.get()).isEqualTo(volumeFlags);
verifyNoMoreInteractions(listener);
future.set(null);
@ -3261,9 +3269,11 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(
new Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_SET_DEVICE_VOLUME)
.remove(Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)
.build())
.build();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_REMOVE_SOUND_AND_VIBRATE;
AtomicInteger flagsFromHandlerRef = new AtomicInteger();
AtomicBoolean callForwarded = new AtomicBoolean();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3273,14 +3283,16 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceVolume(int volume) {
protected ListenableFuture<?> handleSetDeviceVolume(int volume, int flags) {
callForwarded.set(true);
flagsFromHandlerRef.set(flags);
return Futures.immediateVoidFuture();
}
};
player.setDeviceVolume(3);
player.setDeviceVolume(3, volumeFlags);
assertThat(flagsFromHandlerRef.get()).isEqualTo(0); // no flags have been passed
assertThat(callForwarded.get()).isFalse();
}
@ -3292,6 +3304,7 @@ public class SimpleBasePlayerTest {
.setDeviceVolume(3)
.build();
// Set a different one to the one requested to ensure the updated state is used.
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_PLAY_SOUND;
State updatedState = state.buildUpon().setDeviceVolume(6).build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3303,7 +3316,7 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleIncreaseDeviceVolume() {
protected ListenableFuture<?> handleIncreaseDeviceVolume(@C.VolumeFlags int flags) {
playerState = updatedState;
return Futures.immediateVoidFuture();
}
@ -3311,7 +3324,7 @@ public class SimpleBasePlayerTest {
Listener listener = mock(Listener.class);
player.addListener(listener);
player.increaseDeviceVolume();
player.increaseDeviceVolume(volumeFlags);
assertThat(player.getDeviceVolume()).isEqualTo(6);
verify(listener).onDeviceVolumeChanged(6, /* muted= */ false);
@ -3326,6 +3339,7 @@ public class SimpleBasePlayerTest {
.setDeviceVolume(3)
.build();
// Set a new volume to see a difference between the placeholder and new state.
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_PLAY_SOUND;
State updatedState = state.buildUpon().setDeviceVolume(6).build();
SettableFuture<?> future = SettableFuture.create();
SimpleBasePlayer player =
@ -3336,14 +3350,14 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleIncreaseDeviceVolume() {
protected ListenableFuture<?> handleIncreaseDeviceVolume(@C.VolumeFlags int flags) {
return future;
}
};
Listener listener = mock(Listener.class);
player.addListener(listener);
player.increaseDeviceVolume();
player.increaseDeviceVolume(volumeFlags);
// Verify placeholder state and listener calls.
assertThat(player.getDeviceVolume()).isEqualTo(4);
@ -3365,9 +3379,10 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(
new Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME)
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)
.build())
.build();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_PLAY_SOUND;
AtomicBoolean callForwarded = new AtomicBoolean();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3377,13 +3392,13 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleIncreaseDeviceVolume() {
protected ListenableFuture<?> handleIncreaseDeviceVolume(@C.VolumeFlags int flags) {
callForwarded.set(true);
return Futures.immediateVoidFuture();
}
};
player.increaseDeviceVolume();
player.increaseDeviceVolume(volumeFlags);
assertThat(callForwarded.get()).isFalse();
}
@ -3397,6 +3412,7 @@ public class SimpleBasePlayerTest {
.build();
// Set a different one to the one requested to ensure the updated state is used.
State updatedState = state.buildUpon().setDeviceVolume(1).build();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_PLAY_SOUND;
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
private State playerState = state;
@ -3407,7 +3423,7 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleDecreaseDeviceVolume() {
protected ListenableFuture<?> handleDecreaseDeviceVolume(@C.VolumeFlags int flags) {
playerState = updatedState;
return Futures.immediateVoidFuture();
}
@ -3415,7 +3431,7 @@ public class SimpleBasePlayerTest {
Listener listener = mock(Listener.class);
player.addListener(listener);
player.decreaseDeviceVolume();
player.decreaseDeviceVolume(volumeFlags);
assertThat(player.getDeviceVolume()).isEqualTo(1);
verify(listener).onDeviceVolumeChanged(1, /* muted= */ false);
@ -3430,6 +3446,7 @@ public class SimpleBasePlayerTest {
.setDeviceVolume(3)
.build();
// Set a new volume to see a difference between the placeholder and new state.
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
State updatedState = state.buildUpon().setDeviceVolume(1).build();
SettableFuture<?> future = SettableFuture.create();
SimpleBasePlayer player =
@ -3440,14 +3457,14 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleDecreaseDeviceVolume() {
protected ListenableFuture<?> handleDecreaseDeviceVolume(@C.VolumeFlags int flags) {
return future;
}
};
Listener listener = mock(Listener.class);
player.addListener(listener);
player.decreaseDeviceVolume();
player.decreaseDeviceVolume(volumeFlags);
// Verify placeholder state and listener calls.
assertThat(player.getDeviceVolume()).isEqualTo(2);
@ -3469,9 +3486,10 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(
new Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME)
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)
.build())
.build();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
AtomicBoolean callForwarded = new AtomicBoolean();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3481,13 +3499,13 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleDecreaseDeviceVolume() {
protected ListenableFuture<?> handleDecreaseDeviceVolume(@C.VolumeFlags int flags) {
callForwarded.set(true);
return Futures.immediateVoidFuture();
}
};
player.decreaseDeviceVolume();
player.decreaseDeviceVolume(volumeFlags);
assertThat(callForwarded.get()).isFalse();
}
@ -3499,6 +3517,7 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(new Commands.Builder().addAllCommands().build())
.build();
// Also change the volume to ensure the updated state is used.
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
State updatedState = state.buildUpon().setIsDeviceMuted(true).setDeviceVolume(6).build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3510,7 +3529,8 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceMuted(boolean muted) {
protected ListenableFuture<?> handleSetDeviceMuted(
boolean muted, @C.VolumeFlags int flags) {
playerState = updatedState;
return Futures.immediateVoidFuture();
}
@ -3518,7 +3538,7 @@ public class SimpleBasePlayerTest {
Listener listener = mock(Listener.class);
player.addListener(listener);
player.setDeviceMuted(true);
player.setDeviceMuted(true, volumeFlags);
assertThat(player.isDeviceMuted()).isTrue();
assertThat(player.getDeviceVolume()).isEqualTo(6);
@ -3532,6 +3552,7 @@ public class SimpleBasePlayerTest {
new State.Builder()
.setAvailableCommands(new Commands.Builder().addAllCommands().build())
.build();
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
SettableFuture<?> future = SettableFuture.create();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3543,14 +3564,15 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceMuted(boolean muted) {
protected ListenableFuture<?> handleSetDeviceMuted(
boolean muted, @C.VolumeFlags int flags) {
return future;
}
};
Listener listener = mock(Listener.class);
player.addListener(listener);
player.setDeviceMuted(true);
player.setDeviceMuted(true, volumeFlags);
// Verify placeholder state and listener calls.
assertThat(player.isDeviceMuted()).isTrue();
@ -3572,9 +3594,10 @@ public class SimpleBasePlayerTest {
.setAvailableCommands(
new Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME)
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)
.build())
.build();
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
AtomicBoolean callForwarded = new AtomicBoolean();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@ -3584,13 +3607,14 @@ public class SimpleBasePlayerTest {
}
@Override
protected ListenableFuture<?> handleSetDeviceMuted(boolean muted) {
protected ListenableFuture<?> handleSetDeviceMuted(
boolean muted, @C.VolumeFlags int flags) {
callForwarded.set(true);
return Futures.immediateVoidFuture();
}
};
player.setDeviceMuted(true);
player.setDeviceMuted(true, volumeFlags);
assertThat(callForwarded.get()).isFalse();
}

View File

@ -102,11 +102,12 @@ public class StreamVolumeManagerTest {
if (minVolume == maxVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
int oldVolume = streamVolumeManager.getVolume();
int targetVolume = oldVolume == maxVolume ? minVolume : maxVolume;
streamVolumeManager.setVolume(targetVolume);
streamVolumeManager.setVolume(targetVolume, volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(targetVolume);
assertThat(testListener.lastStreamVolume).isEqualTo(targetVolume);
@ -121,11 +122,12 @@ public class StreamVolumeManagerTest {
int maxVolume = streamVolumeManager.getMaxVolume();
int minVolume = streamVolumeManager.getMinVolume();
int oldVolume = streamVolumeManager.getVolume();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(maxVolume + 1);
streamVolumeManager.setVolume(maxVolume + 1, volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(oldVolume);
streamVolumeManager.setVolume(minVolume - 1);
streamVolumeManager.setVolume(minVolume - 1, volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(oldVolume);
});
}
@ -139,11 +141,12 @@ public class StreamVolumeManagerTest {
if (minVolume == maxVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(minVolume);
streamVolumeManager.setVolume(minVolume, volumeFlags);
int targetVolume = minVolume + 1;
streamVolumeManager.increaseVolume();
streamVolumeManager.increaseVolume(volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(targetVolume);
assertThat(testListener.lastStreamVolume).isEqualTo(targetVolume);
@ -156,9 +159,10 @@ public class StreamVolumeManagerTest {
testThread.runOnMainThread(
() -> {
int maxVolume = streamVolumeManager.getMaxVolume();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(maxVolume);
streamVolumeManager.increaseVolume();
streamVolumeManager.setVolume(maxVolume, volumeFlags);
streamVolumeManager.increaseVolume(volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(maxVolume);
});
@ -173,11 +177,12 @@ public class StreamVolumeManagerTest {
if (minVolume == maxVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(maxVolume);
streamVolumeManager.setVolume(maxVolume, volumeFlags);
int targetVolume = maxVolume - 1;
streamVolumeManager.decreaseVolume();
streamVolumeManager.decreaseVolume(volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(targetVolume);
assertThat(testListener.lastStreamVolume).isEqualTo(targetVolume);
@ -190,9 +195,10 @@ public class StreamVolumeManagerTest {
testThread.runOnMainThread(
() -> {
int minVolume = streamVolumeManager.getMinVolume();
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(minVolume);
streamVolumeManager.decreaseVolume();
streamVolumeManager.setVolume(minVolume, volumeFlags);
streamVolumeManager.decreaseVolume(volumeFlags);
assertThat(streamVolumeManager.getVolume()).isEqualTo(minVolume);
});
@ -207,15 +213,16 @@ public class StreamVolumeManagerTest {
if (minVolume == maxVolume || minVolume > 0) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
streamVolumeManager.setVolume(maxVolume);
streamVolumeManager.setVolume(maxVolume, volumeFlags);
assertThat(streamVolumeManager.isMuted()).isFalse();
streamVolumeManager.setMuted(true);
streamVolumeManager.setMuted(true, volumeFlags);
assertThat(streamVolumeManager.isMuted()).isTrue();
assertThat(testListener.lastStreamVolumeMuted).isTrue();
streamVolumeManager.setMuted(false);
streamVolumeManager.setMuted(false, volumeFlags);
assertThat(streamVolumeManager.isMuted()).isFalse();
assertThat(testListener.lastStreamVolumeMuted).isFalse();
assertThat(testListener.lastStreamVolume).isEqualTo(maxVolume);
@ -231,6 +238,7 @@ public class StreamVolumeManagerTest {
if (minVolume == maxVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
int testStreamType = C.STREAM_TYPE_ALARM;
int testStreamVolume = audioManager.getStreamVolume(testStreamType);
@ -238,7 +246,7 @@ public class StreamVolumeManagerTest {
int oldVolume = streamVolumeManager.getVolume();
if (oldVolume == testStreamVolume) {
int differentVolume = oldVolume == minVolume ? maxVolume : minVolume;
streamVolumeManager.setVolume(differentVolume);
streamVolumeManager.setVolume(differentVolume, volumeFlags);
}
streamVolumeManager.setStreamType(testStreamType);

View File

@ -309,7 +309,9 @@ import java.util.concurrent.TimeoutException;
COMMAND_GET_DEVICE_VOLUME,
COMMAND_SET_VOLUME,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_SET_VIDEO_SURFACE,
COMMAND_GET_TEXT,
COMMAND_RELEASE)
@ -1703,28 +1705,68 @@ import java.util.concurrent.TimeoutException;
return streamVolumeManager.isMuted();
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
verifyApplicationThread();
streamVolumeManager.setVolume(volume);
streamVolumeManager.setVolume(volume, C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
verifyApplicationThread();
streamVolumeManager.setVolume(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
verifyApplicationThread();
streamVolumeManager.increaseVolume();
streamVolumeManager.increaseVolume(C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
streamVolumeManager.increaseVolume(flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
verifyApplicationThread();
streamVolumeManager.decreaseVolume();
streamVolumeManager.decreaseVolume(C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
streamVolumeManager.decreaseVolume(flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
verifyApplicationThread();
streamVolumeManager.setMuted(muted);
streamVolumeManager.setMuted(muted, C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
verifyApplicationThread();
streamVolumeManager.setMuted(muted, flags);
}
@Override

View File

@ -1277,30 +1277,70 @@ public class SimpleExoPlayer extends BasePlayer
return player.isDeviceMuted();
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
blockUntilConstructorFinished();
player.setDeviceVolume(volume);
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
blockUntilConstructorFinished();
player.setDeviceVolume(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
blockUntilConstructorFinished();
player.increaseDeviceVolume();
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
blockUntilConstructorFinished();
player.increaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
blockUntilConstructorFinished();
player.decreaseDeviceVolume();
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
blockUntilConstructorFinished();
player.decreaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
blockUntilConstructorFinished();
player.setDeviceMuted(muted);
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
blockUntilConstructorFinished();
player.setDeviceMuted(muted, flags);
}
@Override
public boolean isTunnelingEnabled() {
blockUntilConstructorFinished();

View File

@ -46,9 +46,6 @@ import androidx.media3.common.util.Util;
// Copied from AudioManager#VOLUME_CHANGED_ACTION
private static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
// TODO(b/153317944): Allow users to override these flags.
private static final int VOLUME_FLAGS = AudioManager.FLAG_SHOW_UI;
private final Context applicationContext;
private final Handler eventHandler;
private final Listener listener;
@ -120,46 +117,58 @@ import androidx.media3.common.util.Util;
}
/**
* Sets the volume with the given value for the current audio stream. The value should be between
* {@link #getMinVolume()} and {@link #getMaxVolume()}, otherwise it will be ignored.
* Sets the volume with the given value for the current audio stream with specified volume flags.
*
* @param volume The value should be between {@link #getMinVolume()} and {@link #getMaxVolume()},
* otherwise the volume will not be changed.
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
public void setVolume(int volume) {
public void setVolume(int volume, @C.VolumeFlags int flags) {
if (volume < getMinVolume() || volume > getMaxVolume()) {
return;
}
audioManager.setStreamVolume(streamType, volume, VOLUME_FLAGS);
audioManager.setStreamVolume(streamType, volume, flags);
updateVolumeAndNotifyIfChanged();
}
/**
* Increases the volume by one for the current audio stream. It will be ignored if the current
* volume is equal to {@link #getMaxVolume()}.
* Increases the volume by one for the current audio stream with specified volume flags. If the
* current volume is equal to {@link #getMaxVolume()}, it will not be increased.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
public void increaseVolume() {
public void increaseVolume(@C.VolumeFlags int flags) {
if (volume >= getMaxVolume()) {
return;
}
audioManager.adjustStreamVolume(streamType, AudioManager.ADJUST_RAISE, VOLUME_FLAGS);
audioManager.adjustStreamVolume(streamType, AudioManager.ADJUST_RAISE, flags);
updateVolumeAndNotifyIfChanged();
}
/**
* Decreases the volume by one for the current audio stream. It will be ignored if the current
* volume is equal to {@link #getMinVolume()}.
* Decreases the volume by one for the current audio stream with specified volume flags. If the
* current volume is equal to {@link #getMinVolume()}, it will be be decreased.
*
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
public void decreaseVolume() {
public void decreaseVolume(@C.VolumeFlags int flags) {
if (volume <= getMinVolume()) {
return;
}
audioManager.adjustStreamVolume(streamType, AudioManager.ADJUST_LOWER, VOLUME_FLAGS);
audioManager.adjustStreamVolume(streamType, AudioManager.ADJUST_LOWER, flags);
updateVolumeAndNotifyIfChanged();
}
/** Sets the mute state of the current audio stream. */
public void setMuted(boolean muted) {
/**
* Sets the mute state of the current audio stream with specified volume flags.
*
* @param muted Whether to mute or to unmute the stream.
* @param flags Either 0 or a bitwise combination of one or more {@link C.VolumeFlags}.
*/
public void setMuted(boolean muted, @C.VolumeFlags int flags) {
if (Util.SDK_INT >= 23) {
audioManager.adjustStreamVolume(
streamType, muted ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE, VOLUME_FLAGS);
streamType, muted ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE, flags);
} else {
audioManager.setStreamMute(streamType, muted);
}

View File

@ -16,6 +16,7 @@
package androidx.media3.exoplayer;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
import static androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES;
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
@ -38,6 +39,7 @@ import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_PLAYLIST_METADATA;
import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
@ -12250,11 +12252,13 @@ public final class ExoPlayerTest {
player.addListener(listener);
int deviceVolume = player.getDeviceVolume();
int noVolumeFlags = 0;
int volumeFlags = C.VOLUME_FLAG_PLAY_SOUND | C.VOLUME_FLAG_VIBRATE;
try {
player.setDeviceVolume(deviceVolume + 1); // No-op if at max volume.
player.setDeviceVolume(deviceVolume - 1); // No-op if at min volume.
player.setDeviceVolume(deviceVolume + 1, noVolumeFlags); // No-op if at max volume.
player.setDeviceVolume(deviceVolume - 1, noVolumeFlags); // No-op if at min volume.
} finally {
player.setDeviceVolume(deviceVolume); // Restore original volume.
player.setDeviceVolume(deviceVolume, volumeFlags); // Restore original volume.
}
player.release();
@ -12425,7 +12429,9 @@ public final class ExoPlayerTest {
COMMAND_GET_DEVICE_VOLUME,
COMMAND_SET_VOLUME,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_SET_VIDEO_SURFACE,
COMMAND_GET_TEXT,
COMMAND_SET_TRACK_SELECTION_PARAMETERS,

View File

@ -23,7 +23,6 @@ import androidx.media3.session.IMediaSession;
*
* <p>It's for internal use only, not intended to be used by library users.
*/
// TODO(b/191643508): Hide the generated classes from javadoc.
// Note: Keep this interface oneway. Otherwise a malicious app may make a blocking call to make
// controller frozen.
oneway interface IMediaController {

View File

@ -25,7 +25,6 @@ import androidx.media3.session.IMediaController;
*
* <p>It's for internal use only, not intended to be used by library users.
*/
// TODO(b/191643508): Hide the generated classes from javadoc.
// Note: Keep this interface oneway. Otherwise a malicious app may make a blocking call to make
// session frozen.
oneway interface IMediaSession {
@ -34,9 +33,13 @@ oneway interface IMediaSession {
void setVolume(IMediaController caller, int seq, float volume) = 3001;
void setDeviceVolume(IMediaController caller, int seq, int volume) = 3002;
void setDeviceVolumeWithFlags(IMediaController caller, int seq, int volume, int flags) = 3050;
void increaseDeviceVolume(IMediaController caller, int seq) = 3003;
void increaseDeviceVolumeWithFlags(IMediaController caller, int seq, int flags) = 3051;
void decreaseDeviceVolume(IMediaController caller, int seq) = 3004;
void decreaseDeviceVolumeWithFlags(IMediaController caller, int seq, int flags) = 3052;
void setDeviceMuted(IMediaController caller, int seq, boolean muted) = 3005;
void setDeviceMutedWithFlags(IMediaController caller, int seq, boolean muted, int flags) = 3053;
void setMediaItem(
IMediaController caller,
int seq,
@ -115,7 +118,7 @@ oneway interface IMediaSession {
void setRatingWithMediaId(
IMediaController caller, int seq, String mediaId, in Bundle rating) = 3048;
void setRating(IMediaController caller, int seq, in Bundle rating) = 3049;
// Next Id for MediaSession: 3050
// Next Id for MediaSession: 3054
void getLibraryRoot(IMediaController caller, int seq, in Bundle libraryParams) = 4000;
void getItem(IMediaController caller, int seq, String mediaId) = 4001;

View File

@ -22,7 +22,6 @@ import androidx.media3.session.IMediaController;
*
* <p>It's for internal use only, not intended to be used by library users.
*/
// TODO(b/191643508): Hide the generated classes from javadoc.
// Note: Keep this interface oneway. Otherwise a malicious app may make a blocking call to make
// session service frozen.
oneway interface IMediaSessionService {

View File

@ -1667,6 +1667,10 @@ public class MediaController implements Player {
return impl.isDeviceMuted();
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public final void setDeviceVolume(@IntRange(from = 0) int volume) {
verifyApplicationThread();
@ -1677,6 +1681,19 @@ public class MediaController implements Player {
impl.setDeviceVolume(volume);
}
@Override
public final void setDeviceVolume(@IntRange(from = 0) int volume, @C.VolumeFlags int flags) {
verifyApplicationThread();
if (!isConnected()) {
Log.w(TAG, "The controller is not connected. Ignoring setDeviceVolume().");
return;
}
impl.setDeviceVolume(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public final void increaseDeviceVolume() {
verifyApplicationThread();
@ -1687,6 +1704,19 @@ public class MediaController implements Player {
impl.increaseDeviceVolume();
}
@Override
public final void increaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
if (!isConnected()) {
Log.w(TAG, "The controller is not connected. Ignoring increaseDeviceVolume().");
return;
}
impl.increaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public final void decreaseDeviceVolume() {
verifyApplicationThread();
@ -1697,6 +1727,19 @@ public class MediaController implements Player {
impl.decreaseDeviceVolume();
}
@Override
public final void decreaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
if (!isConnected()) {
Log.w(TAG, "The controller is not connected. Ignoring decreaseDeviceVolume().");
return;
}
impl.decreaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public final void setDeviceMuted(boolean muted) {
verifyApplicationThread();
@ -1707,6 +1750,16 @@ public class MediaController implements Player {
impl.setDeviceMuted(muted);
}
@Override
public final void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
verifyApplicationThread();
if (!isConnected()) {
Log.w(TAG, "The controller is not connected. Ignoring setDeviceMuted().");
return;
}
impl.setDeviceMuted(muted, flags);
}
@Override
public final MediaMetadata getMediaMetadata() {
verifyApplicationThread();
@ -2033,12 +2086,20 @@ public class MediaController implements Player {
void setDeviceVolume(int volume);
void setDeviceVolume(int volume, @C.VolumeFlags int flags);
void increaseDeviceVolume();
void increaseDeviceVolume(@C.VolumeFlags int flags);
void decreaseDeviceVolume();
void decreaseDeviceVolume(@C.VolumeFlags int flags);
void setDeviceMuted(boolean muted);
void setDeviceMuted(boolean muted, @C.VolumeFlags int flags);
boolean getPlayWhenReady();
@PlaybackSuppressionReason

View File

@ -1386,6 +1386,10 @@ import org.checkerframework.checker.nullness.qual.NonNull;
return playerInfo.deviceMuted;
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
if (!isPlayerCommandAvailable(Player.COMMAND_SET_DEVICE_VOLUME)) {
@ -1405,6 +1409,29 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
if (!isPlayerCommandAvailable(Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.setDeviceVolumeWithFlags(controllerStub, seq, volume, flags));
if (playerInfo.deviceVolume != volume) {
playerInfo = playerInfo.copyWithDeviceVolume(volume, playerInfo.deviceMuted);
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(volume, playerInfo.deviceMuted));
listeners.flushEvents();
}
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME)) {
@ -1424,6 +1451,29 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.increaseDeviceVolumeWithFlags(controllerStub, seq, flags));
int newDeviceVolume = playerInfo.deviceVolume + 1;
if (newDeviceVolume <= getDeviceInfo().maxVolume) {
playerInfo = playerInfo.copyWithDeviceVolume(newDeviceVolume, playerInfo.deviceMuted);
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(newDeviceVolume, playerInfo.deviceMuted));
listeners.flushEvents();
}
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME)) {
@ -1443,6 +1493,29 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.decreaseDeviceVolumeWithFlags(controllerStub, seq, flags));
int newDeviceVolume = playerInfo.deviceVolume - 1;
if (newDeviceVolume >= getDeviceInfo().minVolume) {
playerInfo = playerInfo.copyWithDeviceVolume(newDeviceVolume, playerInfo.deviceMuted);
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(newDeviceVolume, playerInfo.deviceMuted));
listeners.flushEvents();
}
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME)) {
@ -1461,6 +1534,24 @@ import org.checkerframework.checker.nullness.qual.NonNull;
}
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
if (!isPlayerCommandAvailable(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
dispatchRemoteSessionTaskWithPlayerCommand(
(iSession, seq) -> iSession.setDeviceMutedWithFlags(controllerStub, seq, muted, flags));
if (playerInfo.deviceMuted != muted) {
playerInfo = playerInfo.copyWithDeviceVolume(playerInfo.deviceVolume, muted);
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_DEVICE_VOLUME_CHANGED,
listener -> listener.onDeviceVolumeChanged(playerInfo.deviceVolume, muted));
listeners.flushEvents();
}
}
@Override
public VideoSize getVideoSize() {
return playerInfo.videoSize;

View File

@ -91,7 +91,6 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private static final String TAG = "MCImplLegacy";
private static final long AGGREGATES_CALLBACKS_WITHIN_TIMEOUT_MS = 500L;
private static final int VOLUME_FLAGS = AudioManager.FLAG_SHOW_UI;
/* package */ final Context context;
private final MediaController instance;
@ -1050,8 +1049,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
return controllerInfo.playerInfo.deviceMuted;
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
setDeviceVolume(volume, C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
DeviceInfo deviceInfo = getDeviceInfo();
int minVolume = deviceInfo.minVolume;
int maxVolume = deviceInfo.maxVolume;
@ -1069,11 +1077,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/* mediaItemTransitionReason= */ null);
}
controllerCompat.setVolumeTo(volume, VOLUME_FLAGS);
controllerCompat.setVolumeTo(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
increaseDeviceVolume(C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void increaseDeviceVolume() {
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
int volume = getDeviceVolume();
int maxVolume = getDeviceInfo().maxVolume;
if (volume + 1 <= maxVolume) {
@ -1090,11 +1107,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/* discontinuityReason= */ null,
/* mediaItemTransitionReason= */ null);
}
controllerCompat.adjustVolume(AudioManager.ADJUST_RAISE, VOLUME_FLAGS);
controllerCompat.adjustVolume(AudioManager.ADJUST_RAISE, flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
decreaseDeviceVolume(C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void decreaseDeviceVolume() {
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
int volume = getDeviceVolume();
int minVolume = getDeviceInfo().minVolume;
@ -1111,11 +1137,20 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
/* discontinuityReason= */ null,
/* mediaItemTransitionReason= */ null);
}
controllerCompat.adjustVolume(AudioManager.ADJUST_LOWER, VOLUME_FLAGS);
controllerCompat.adjustVolume(AudioManager.ADJUST_LOWER, flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
setDeviceMuted(muted, C.VOLUME_FLAG_SHOW_UI);
}
@Override
public void setDeviceMuted(boolean muted) {
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
if (Util.SDK_INT < 23) {
Log.w(TAG, "Session doesn't support setting mute state at API level less than 23");
return;
@ -1137,7 +1172,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
}
int direction = muted ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE;
controllerCompat.adjustVolume(direction, VOLUME_FLAGS);
controllerCompat.adjustVolume(direction, flags);
}
@Override

View File

@ -16,6 +16,7 @@
package androidx.media3.session;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE;
import static androidx.media3.common.Player.COMMAND_PREPARE;
@ -29,6 +30,7 @@ import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_PLAYLIST_METADATA;
import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
@ -1332,6 +1334,7 @@ import java.util.concurrent.ExecutionException;
sendSessionResultSuccess(player -> player.setVolume(volume)));
}
@SuppressWarnings("deprecation") // Backwards compatibility a for flag-less method
@Override
public void setDeviceVolume(@Nullable IMediaController caller, int sequenceNumber, int volume) {
if (caller == null) {
@ -1344,6 +1347,20 @@ import java.util.concurrent.ExecutionException;
sendSessionResultSuccess(player -> player.setDeviceVolume(volume)));
}
@Override
public void setDeviceVolumeWithFlags(
@Nullable IMediaController caller, int sequenceNumber, int volume, int flags) {
if (caller == null) {
return;
}
queueSessionTaskWithPlayerCommand(
caller,
sequenceNumber,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
sendSessionResultSuccess(player -> player.setDeviceVolume(volume, flags)));
}
@SuppressWarnings("deprecation") // Backwards compatibility a for flag-less method
@Override
public void increaseDeviceVolume(@Nullable IMediaController caller, int sequenceNumber) {
if (caller == null) {
@ -1353,9 +1370,23 @@ import java.util.concurrent.ExecutionException;
caller,
sequenceNumber,
COMMAND_ADJUST_DEVICE_VOLUME,
sendSessionResultSuccess(Player::increaseDeviceVolume));
sendSessionResultSuccess(player -> player.increaseDeviceVolume()));
}
@Override
public void increaseDeviceVolumeWithFlags(
@Nullable IMediaController caller, int sequenceNumber, int flags) {
if (caller == null) {
return;
}
queueSessionTaskWithPlayerCommand(
caller,
sequenceNumber,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
sendSessionResultSuccess(player -> player.increaseDeviceVolume(flags)));
}
@SuppressWarnings("deprecation") // Backwards compatibility a for flag-less method
@Override
public void decreaseDeviceVolume(@Nullable IMediaController caller, int sequenceNumber) {
if (caller == null) {
@ -1365,9 +1396,23 @@ import java.util.concurrent.ExecutionException;
caller,
sequenceNumber,
COMMAND_ADJUST_DEVICE_VOLUME,
sendSessionResultSuccess(Player::decreaseDeviceVolume));
sendSessionResultSuccess(player -> player.decreaseDeviceVolume()));
}
@Override
public void decreaseDeviceVolumeWithFlags(
@Nullable IMediaController caller, int sequenceNumber, int flags) {
if (caller == null) {
return;
}
queueSessionTaskWithPlayerCommand(
caller,
sequenceNumber,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
sendSessionResultSuccess(player -> player.decreaseDeviceVolume(flags)));
}
@SuppressWarnings("deprecation") // Backwards compatibility a for flag-less method
@Override
public void setDeviceMuted(@Nullable IMediaController caller, int sequenceNumber, boolean muted) {
if (caller == null) {
@ -1380,6 +1425,19 @@ import java.util.concurrent.ExecutionException;
sendSessionResultSuccess(player -> player.setDeviceMuted(muted)));
}
@Override
public void setDeviceMutedWithFlags(
@Nullable IMediaController caller, int sequenceNumber, boolean muted, int flags) {
if (caller == null) {
return;
}
queueSessionTaskWithPlayerCommand(
caller,
sequenceNumber,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
sendSessionResultSuccess(player -> player.setDeviceMuted(muted, flags)));
}
@Override
public void setPlayWhenReady(
@Nullable IMediaController caller, int sequenceNumber, boolean playWhenReady) {

View File

@ -18,6 +18,7 @@ package androidx.media3.session;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS;
import static androidx.media.utils.MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_CHANGE_MEDIA_ITEMS;
import static androidx.media3.common.Player.COMMAND_GET_AUDIO_ATTRIBUTES;
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
@ -36,6 +37,7 @@ import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME;
import static androidx.media3.common.Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS;
import static androidx.media3.common.Player.COMMAND_SET_MEDIA_ITEM;
import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE;
@ -1094,6 +1096,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
* @param isSessionReady Whether the session compat is ready.
* @return The converted player commands.
*/
@SuppressWarnings("deprecation") // Backwards compatibility with old volume commands
public static Player.Commands convertToPlayerCommands(
@Nullable PlaybackStateCompat playbackStateCompat,
int volumeControlType,
@ -1141,9 +1144,14 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
playerCommandsBuilder.add(COMMAND_STOP);
}
if (volumeControlType == VolumeProviderCompat.VOLUME_CONTROL_RELATIVE) {
playerCommandsBuilder.add(COMMAND_ADJUST_DEVICE_VOLUME);
playerCommandsBuilder.addAll(
COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS);
} else if (volumeControlType == VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE) {
playerCommandsBuilder.addAll(COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_SET_DEVICE_VOLUME);
playerCommandsBuilder.addAll(
COMMAND_ADJUST_DEVICE_VOLUME,
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS,
COMMAND_SET_DEVICE_VOLUME,
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS);
}
playerCommandsBuilder.addAll(
COMMAND_GET_DEVICE_VOLUME,

View File

@ -736,36 +736,74 @@ import java.util.List;
return isCommandAvailable(Player.COMMAND_GET_DEVICE_VOLUME) && isDeviceMuted();
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@SuppressWarnings("deprecation") // Forwarding to deprecated method
@Deprecated
@Override
public void setDeviceVolume(int volume) {
verifyApplicationThread();
super.setDeviceVolume(volume);
}
public void setDeviceVolumeIfCommandAvailable(int volume) {
if (isCommandAvailable(COMMAND_SET_DEVICE_VOLUME)) {
setDeviceVolume(volume);
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
verifyApplicationThread();
super.setDeviceVolume(volume, flags);
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@SuppressWarnings("deprecation") // Forwarding to deprecated method
@Deprecated
@Override
public void increaseDeviceVolume() {
verifyApplicationThread();
super.increaseDeviceVolume();
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
super.increaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@SuppressWarnings("deprecation") // Forwarding to deprecated method
@Deprecated
@Override
public void decreaseDeviceVolume() {
verifyApplicationThread();
super.decreaseDeviceVolume();
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
verifyApplicationThread();
super.decreaseDeviceVolume(flags);
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@SuppressWarnings("deprecation") // Forwarding to deprecated method
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
verifyApplicationThread();
super.setDeviceMuted(muted);
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
verifyApplicationThread();
super.setDeviceMuted(muted, flags);
}
@Override
public void setPlayWhenReady(boolean playWhenReady) {
verifyApplicationThread();
@ -974,6 +1012,7 @@ import java.util.List;
}
@Nullable
@SuppressWarnings("deprecation") // Backwards compatibility with old volume commands
public VolumeProviderCompat createVolumeProviderCompat() {
if (getDeviceInfo().playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
return null;
@ -988,10 +1027,23 @@ import java.util.List;
}
Handler handler = new Handler(getApplicationLooper());
int currentVolume = getDeviceVolumeWithCommandCheck();
int legacyVolumeFlag = C.VOLUME_FLAG_SHOW_UI;
return new VolumeProviderCompat(volumeControlType, getDeviceInfo().maxVolume, currentVolume) {
@Override
public void onSetVolumeTo(int volume) {
postOrRun(handler, () -> setDeviceVolumeIfCommandAvailable(volume));
postOrRun(
handler,
() -> {
if (!isCommandAvailable(COMMAND_SET_DEVICE_VOLUME)
&& !isCommandAvailable(COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
if (isCommandAvailable(COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)) {
setDeviceVolume(volume, legacyVolumeFlag);
} else {
setDeviceVolume(volume);
}
});
}
@Override
@ -999,24 +1051,45 @@ import java.util.List;
postOrRun(
handler,
() -> {
if (!isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)) {
if (!isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)
&& !isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
return;
}
switch (direction) {
case AudioManager.ADJUST_RAISE:
increaseDeviceVolume();
if (isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
increaseDeviceVolume(legacyVolumeFlag);
} else {
increaseDeviceVolume();
}
break;
case AudioManager.ADJUST_LOWER:
decreaseDeviceVolume();
if (isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
decreaseDeviceVolume(legacyVolumeFlag);
} else {
decreaseDeviceVolume();
}
break;
case AudioManager.ADJUST_MUTE:
setDeviceMuted(true);
if (isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
setDeviceMuted(true, legacyVolumeFlag);
} else {
setDeviceMuted(true);
}
break;
case AudioManager.ADJUST_UNMUTE:
setDeviceMuted(false);
if (isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
setDeviceMuted(false, legacyVolumeFlag);
} else {
setDeviceMuted(false);
}
break;
case AudioManager.ADJUST_TOGGLE_MUTE:
setDeviceMuted(!isDeviceMutedWithCommandCheck());
if (isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)) {
setDeviceMuted(!isDeviceMutedWithCommandCheck(), legacyVolumeFlag);
} else {
setDeviceMuted(!isDeviceMutedWithCommandCheck());
}
break;
default:
Log.w(

View File

@ -72,9 +72,13 @@ interface IRemoteMediaController {
void adjustVolume(String controllerId, int direction, int flags);
void setVolume(String controllerId, float volume);
void setDeviceVolume(String controllerId, int volume);
void setDeviceVolumeWithFlags(String controllerId, int volume, int flags);
void increaseDeviceVolume(String controllerId);
void increaseDeviceVolumeWithFlags(String controllerId, int flags);
void decreaseDeviceVolume(String controllerId);
void decreaseDeviceVolumeWithFlags(String controllerId, int flags);
void setDeviceMuted(String controllerId, boolean muted);
void setDeviceMutedWithFlags(String controllerId, boolean muted, int flags);
Bundle sendCustomCommand(String controllerId, in Bundle command, in Bundle args);
Bundle setRatingWithMediaId(String controllerId, String mediaId, in Bundle rating);
Bundle setRating(String controllerId, in Bundle rating);

View File

@ -52,6 +52,10 @@ interface IRemoteMediaSession {
void setCurrentAdGroupIndex(String sessionId, int currentAdGroupIndex);
void setCurrentAdIndexInAdGroup(String sessionId, int currentAdIndexInAdGroup);
void setVolume(String sessionId, float volume);
void setDeviceVolume(String sessionId, int volume, int flags);
void decreaseDeviceVolume(String sessionId, int flags);
void increaseDeviceVolume(String sessionId, int flags);
void setDeviceMuted(String sessionId, boolean muted, int flags);
void notifyPlayerError(String sessionId, in Bundle playerErrorBundle);
void notifyPlayWhenReadyChanged(String sessionId, boolean playWhenReady, int reason);
void notifyPlaybackStateChanged(String sessionId, int state);
@ -79,9 +83,8 @@ interface IRemoteMediaSession {
void notifyRepeatModeChanged(String sessionId);
void notifySeekBackIncrementChanged(String sessionId, long seekBackIncrementMs);
void notifySeekForwardIncrementChanged(String sessionId, long seekForwardIncrementMs);
void notifyDeviceVolumeChanged(String sessionId, int volume, boolean muted);
void decreaseDeviceVolume(String sessionId);
void increaseDeviceVolume(String sessionId);
void notifyDeviceVolumeChanged(String sessionId);
void notifyVolumeChanged(String sessionId);
void notifyCuesChanged(String sessionId, in Bundle cueGroup);
void notifyDeviceInfoChanged(String sessionId, in Bundle deviceInfo);
void notifyMediaMetadataChanged(String sessionId, in Bundle mediaMetadata);

View File

@ -1286,7 +1286,8 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
};
controllerCompat.registerCallback(callback, handler);
session.getMockPlayer().notifyDeviceVolumeChanged(targetVolume, /* muted= */ false);
session.getMockPlayer().setDeviceVolume(targetVolume, /* flags= */ 0);
session.getMockPlayer().notifyDeviceVolumeChanged();
assertThat(targetVolumeNotified.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(controllerCompat.getPlaybackInfo().getCurrentVolume()).isEqualTo(targetVolume);

View File

@ -2850,7 +2850,8 @@ public class MediaControllerListenerTest {
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
int targetVolume = 45;
remoteSession.getMockPlayer().notifyDeviceVolumeChanged(targetVolume, /* muted= */ false);
remoteSession.getMockPlayer().setDeviceVolume(targetVolume, /* flags= */ 0);
remoteSession.getMockPlayer().notifyDeviceVolumeChanged();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromParamRef.get()).isEqualTo(targetVolume);
@ -2889,7 +2890,8 @@ public class MediaControllerListenerTest {
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
remoteSession.getMockPlayer().notifyDeviceVolumeChanged(/* volume= */ 0, /* muted= */ true);
remoteSession.getMockPlayer().setDeviceMuted(/* muted= */ true, /* flags= */ 0);
remoteSession.getMockPlayer().notifyDeviceVolumeChanged();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceMutedFromParamRef.get()).isTrue();
@ -2904,6 +2906,7 @@ public class MediaControllerListenerTest {
new RemoteMediaSession.MockPlayerConfigBuilder().setDeviceVolume(10).build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
AtomicInteger deviceVolumeFromParamRef = new AtomicInteger();
AtomicInteger deviceVolumeFromGetterRef = new AtomicInteger();
AtomicInteger deviceVolumeFromOnEventsRef = new AtomicInteger();
@ -2927,7 +2930,8 @@ public class MediaControllerListenerTest {
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
remoteSession.getMockPlayer().decreaseDeviceVolume();
remoteSession.getMockPlayer().decreaseDeviceVolume(volumeFlags);
remoteSession.getMockPlayer().notifyDeviceVolumeChanged();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromParamRef.get()).isEqualTo(9);
@ -2943,6 +2947,7 @@ public class MediaControllerListenerTest {
new RemoteMediaSession.MockPlayerConfigBuilder().setDeviceVolume(10).build();
remoteSession.setPlayer(playerConfig);
MediaController controller = controllerTestRule.createController(remoteSession.getToken());
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
AtomicInteger deviceVolumeFromParamRef = new AtomicInteger();
AtomicInteger deviceVolumeFromGetterRef = new AtomicInteger();
AtomicInteger deviceVolumeFromOnEventsRef = new AtomicInteger();
@ -2966,7 +2971,8 @@ public class MediaControllerListenerTest {
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
remoteSession.getMockPlayer().increaseDeviceVolume();
remoteSession.getMockPlayer().increaseDeviceVolume(volumeFlags);
remoteSession.getMockPlayer().notifyDeviceVolumeChanged();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(deviceVolumeFromParamRef.get()).isEqualTo(11);
@ -3005,6 +3011,7 @@ public class MediaControllerListenerTest {
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
remoteSession.getMockPlayer().setVolume(0.5f);
remoteSession.getMockPlayer().notifyVolumeChanged();
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(volumeFromParamRef.get()).isEqualTo(0.5f);

View File

@ -437,6 +437,7 @@ public class MediaControllerStateMaskingTest {
@Test
public void setDeviceVolume() throws Exception {
int testDeviceVolume = 2;
int volumeFlags = 0;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder().setDeviceVolume(0).build();
remoteSession.setPlayer(playerConfig);
@ -466,7 +467,7 @@ public class MediaControllerStateMaskingTest {
.getHandler()
.postAndSync(
() -> {
controller.setDeviceVolume(testDeviceVolume);
controller.setDeviceVolume(testDeviceVolume, volumeFlags);
deviceVolumeFromGetterRef.set(controller.getDeviceVolume());
});
@ -480,6 +481,7 @@ public class MediaControllerStateMaskingTest {
@Test
public void increaseDeviceVolume() throws Exception {
int testDeviceVolume = 2;
int volumeFlags = 0;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder()
.setDeviceVolume(1)
@ -514,7 +516,7 @@ public class MediaControllerStateMaskingTest {
.getHandler()
.postAndSync(
() -> {
controller.increaseDeviceVolume();
controller.increaseDeviceVolume(volumeFlags);
deviceVolumeFromGetterRef.set(controller.getDeviceVolume());
});
@ -552,12 +554,13 @@ public class MediaControllerStateMaskingTest {
};
threadTestRule.getHandler().postAndSync(() -> controller.addListener(listener));
int volumeFlags = 0;
AtomicInteger deviceVolumeFromGetterRef = new AtomicInteger();
threadTestRule
.getHandler()
.postAndSync(
() -> {
controller.decreaseDeviceVolume();
controller.decreaseDeviceVolume(volumeFlags);
deviceVolumeFromGetterRef.set(controller.getDeviceVolume());
});
@ -571,6 +574,7 @@ public class MediaControllerStateMaskingTest {
@Test
public void setDeviceMuted() throws Exception {
boolean testDeviceMuted = true;
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
Bundle playerConfig =
new RemoteMediaSession.MockPlayerConfigBuilder().setDeviceMuted(false).build();
remoteSession.setPlayer(playerConfig);
@ -600,7 +604,7 @@ public class MediaControllerStateMaskingTest {
.getHandler()
.postAndSync(
() -> {
controller.setDeviceMuted(testDeviceMuted);
controller.setDeviceMuted(testDeviceMuted, volumeFlags);
deviceMutedFromGetterRef.set(controller.isDeviceMuted());
});

View File

@ -43,6 +43,7 @@ import android.support.v4.media.session.PlaybackStateCompat;
import androidx.media.AudioAttributesCompat;
import androidx.media.AudioManagerCompat;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
import androidx.media3.common.DeviceInfo;
import androidx.media3.common.MediaItem;
import androidx.media3.common.Player;
@ -664,6 +665,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
remotePlayer.commands =
new Player.Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)
.build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -680,6 +686,35 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
}
@Test
public void setVolumeTo_setsDeviceVolumeWithFlags() throws Exception {
session =
new MediaSession.Builder(context, player)
.setId("setVolumeTo_setsDeviceVolumeWithFlags")
.setCallback(new TestSessionCallback())
.build();
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
remotePlayer.commands = new Player.Commands.Builder().addAllCommands().build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
new DeviceInfo(
DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 0, /* maxVolume= */ 100);
remotePlayer.deviceVolume = 23;
session.setPlayer(remotePlayer);
});
int targetVolume = 50;
controller.setVolumeTo(targetVolume, /* flags= */ 0);
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
}
@Test
public void adjustVolume_raise_increasesDeviceVolume() throws Exception {
session =
@ -692,6 +727,37 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
remotePlayer.commands =
new Player.Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)
.build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
new DeviceInfo(
DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 0, /* maxVolume= */ 100);
remotePlayer.deviceVolume = 23;
session.setPlayer(remotePlayer);
});
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
public void adjustVolume_raise_increasesDeviceVolumeWithFlags() throws Exception {
session =
new MediaSession.Builder(context, player)
.setId("adjustVolume_raise_increasesDeviceVolumeWithFlags")
.setCallback(new TestSessionCallback())
.build();
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -703,7 +769,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
}
@Test
@ -718,6 +784,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
remotePlayer.commands =
new Player.Commands.Builder()
.addAllCommands()
.remove(Player.COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)
.build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -732,6 +803,33 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
public void adjustVolume_lower_decreasesDeviceVolumeWithFlags() throws Exception {
session =
new MediaSession.Builder(context, player)
.setId("adjustVolume_lower_decreasesDeviceVolumeWithFlags")
.setCallback(new TestSessionCallback())
.build();
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
remotePlayer.commands = new Player.Commands.Builder().addAllCommands().build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
new DeviceInfo(
DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 0, /* maxVolume= */ 100);
remotePlayer.deviceVolume = 23;
session.setPlayer(remotePlayer);
});
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS, TIMEOUT_MS);
}
@Test
public void setVolumeWithLocalVolume() throws Exception {
if (Util.SDK_INT >= 21 && audioManager.isVolumeFixed()) {
@ -772,7 +870,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
int targetVolume = originalVolume == minVolume ? originalVolume + 1 : originalVolume - 1;
Log.d(TAG, "originalVolume=" + originalVolume + ", targetVolume=" + targetVolume);
controller.setVolumeTo(targetVolume, AudioManager.FLAG_SHOW_UI);
controller.setVolumeTo(targetVolume, C.VOLUME_FLAG_SHOW_UI);
PollingCheck.waitFor(
VOLUME_CHANGE_TIMEOUT_MS, () -> targetVolume == audioManager.getStreamVolume(stream));
@ -822,7 +920,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
int targetVolume = originalVolume + direction;
Log.d(TAG, "originalVolume=" + originalVolume + ", targetVolume=" + targetVolume);
controller.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
controller.adjustVolume(direction, C.VOLUME_FLAG_SHOW_UI);
PollingCheck.waitFor(
VOLUME_CHANGE_TIMEOUT_MS, () -> targetVolume == audioManager.getStreamVolume(stream));

View File

@ -529,12 +529,13 @@ public class MediaSessionCompatCallbackWithMediaControllerTest {
int maxVolume = 100;
int currentVolume = 23;
int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
int volumeFlags = C.VOLUME_FLAG_SHOW_UI;
TestVolumeProvider volumeProvider =
new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
session.setPlaybackToRemote(volumeProvider);
RemoteMediaController controller = createControllerAndWaitConnection();
controller.decreaseDeviceVolume();
controller.decreaseDeviceVolume(volumeFlags);
assertThat(volumeProvider.latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(volumeProvider.adjustVolumeCalled).isTrue();
assertThat(volumeProvider.direction).isEqualTo(AudioManager.ADJUST_LOWER);
@ -554,12 +555,14 @@ public class MediaSessionCompatCallbackWithMediaControllerTest {
if (maxVolume <= minVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
session.setPlaybackToLocal(stream);
RemoteMediaController controller = createControllerAndWaitConnection();
int originalVolume = audioManager.getStreamVolume(stream);
int targetVolume = originalVolume == minVolume ? originalVolume + 1 : originalVolume - 1;
controller.setDeviceVolume(targetVolume);
controller.setDeviceVolume(targetVolume, volumeFlags);
PollingCheck.waitFor(
VOLUME_CHANGE_TIMEOUT_MS, () -> targetVolume == audioManager.getStreamVolume(stream));
@ -581,13 +584,15 @@ public class MediaSessionCompatCallbackWithMediaControllerTest {
if (maxVolume <= minVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
session.setPlaybackToLocal(stream);
RemoteMediaController controller = createControllerAndWaitConnection();
int originalVolume = audioManager.getStreamVolume(stream);
audioManager.setStreamVolume(stream, minVolume, /* flags= */ 0);
int targetVolume = minVolume + 1;
controller.increaseDeviceVolume();
controller.increaseDeviceVolume(volumeFlags);
PollingCheck.waitFor(
VOLUME_CHANGE_TIMEOUT_MS, () -> targetVolume == audioManager.getStreamVolume(stream));
@ -609,13 +614,15 @@ public class MediaSessionCompatCallbackWithMediaControllerTest {
if (maxVolume <= minVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_SHOW_UI | C.VOLUME_FLAG_VIBRATE;
session.setPlaybackToLocal(stream);
RemoteMediaController controller = createControllerAndWaitConnection();
int originalVolume = audioManager.getStreamVolume(stream);
audioManager.setStreamVolume(stream, maxVolume, /* flags= */ 0);
int targetVolume = maxVolume - 1;
controller.decreaseDeviceVolume();
controller.decreaseDeviceVolume(volumeFlags);
PollingCheck.waitFor(
VOLUME_CHANGE_TIMEOUT_MS, () -> targetVolume == audioManager.getStreamVolume(stream));
@ -637,12 +644,14 @@ public class MediaSessionCompatCallbackWithMediaControllerTest {
if (maxVolume <= minVolume) {
return;
}
int volumeFlags = C.VOLUME_FLAG_VIBRATE;
session.setPlaybackToLocal(stream);
RemoteMediaController controller = createControllerAndWaitConnection();
boolean wasMuted = audioManager.isStreamMute(stream);
audioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, /* flags= */ 0);
controller.setDeviceMuted(true);
controller.setDeviceMuted(true, volumeFlags);
PollingCheck.waitFor(VOLUME_CHANGE_TIMEOUT_MS, () -> audioManager.isStreamMute(stream));
// Set back to original mute state.

View File

@ -17,6 +17,7 @@ package androidx.media3.session;
import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackParameters;
@ -437,6 +438,17 @@ public class MockPlayerTest {
assertThat(player.deviceVolume).isEqualTo(testVolume);
}
@Test
public void setDeviceVolumeWithFlags() {
int testVolume = 12;
int testVolumeFlags = C.VOLUME_FLAG_VIBRATE;
player.setDeviceVolume(testVolume, testVolumeFlags);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME_WITH_FLAGS)).isTrue();
assertThat(player.deviceVolume).isEqualTo(testVolume);
}
@Test
public void increaseDeviceVolume() {
player.increaseDeviceVolume();
@ -444,6 +456,15 @@ public class MockPlayerTest {
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME)).isTrue();
}
@Test
public void increaseDeviceVolumeWithFlags() {
int testVolumeFlags = C.VOLUME_FLAG_VIBRATE | C.VOLUME_FLAG_PLAY_SOUND;
player.increaseDeviceVolume(testVolumeFlags);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS))
.isTrue();
}
@Test
public void decreaseDeviceVolume() {
player.decreaseDeviceVolume();
@ -451,6 +472,15 @@ public class MockPlayerTest {
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME)).isTrue();
}
@Test
public void decreaseDeviceVolumeWithFlags() {
int testVolumeFlags = C.VOLUME_FLAG_SHOW_UI;
player.decreaseDeviceVolume(testVolumeFlags);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS))
.isTrue();
}
@Test
public void setDeviceMuted() {
player.deviceMuted = false;
@ -461,6 +491,17 @@ public class MockPlayerTest {
assertThat(player.deviceMuted).isTrue();
}
@Test
public void setDeviceMutedWithFlags() {
player.deviceMuted = false;
int testVolumeFlags = 0;
player.setDeviceMuted(true, testVolumeFlags);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_DEVICE_MUTED_WITH_FLAGS)).isTrue();
assertThat(player.deviceMuted).isTrue();
}
@Test
public void setTrackSelectionParameters() {
TrackSelectionParameters trackSelectionParameters =

View File

@ -523,7 +523,7 @@ public class MediaControllerProviderService extends Service {
runOnHandler(
() -> {
MediaController controller = mediaControllerMap.get(controllerId);
controller.setDeviceVolume(value);
controller.setDeviceVolume(value, flags);
});
}
@ -534,19 +534,19 @@ public class MediaControllerProviderService extends Service {
MediaController controller = mediaControllerMap.get(controllerId);
switch (direction) {
case AudioManager.ADJUST_RAISE:
controller.increaseDeviceVolume();
controller.increaseDeviceVolume(flags);
break;
case AudioManager.ADJUST_LOWER:
controller.decreaseDeviceVolume();
controller.decreaseDeviceVolume(flags);
break;
case AudioManager.ADJUST_MUTE:
controller.setDeviceMuted(true);
controller.setDeviceMuted(true, flags);
break;
case AudioManager.ADJUST_UNMUTE:
controller.setDeviceMuted(false);
controller.setDeviceMuted(false, flags);
break;
case AudioManager.ADJUST_TOGGLE_MUTE:
controller.setDeviceMuted(controller.isDeviceMuted());
controller.setDeviceMuted(controller.isDeviceMuted(), flags);
break;
default:
throw new IllegalArgumentException("Unknown direction: " + direction);
@ -602,6 +602,16 @@ public class MediaControllerProviderService extends Service {
});
}
@Override
public void setDeviceVolumeWithFlags(String controllerId, int volume, int flags)
throws RemoteException {
runOnHandler(
() -> {
MediaController controller = mediaControllerMap.get(controllerId);
controller.setDeviceVolume(volume, flags);
});
}
@Override
public void increaseDeviceVolume(String controllerId) throws RemoteException {
runOnHandler(
@ -611,6 +621,16 @@ public class MediaControllerProviderService extends Service {
});
}
@Override
public void increaseDeviceVolumeWithFlags(String controllerId, int flags)
throws RemoteException {
runOnHandler(
() -> {
MediaController controller = mediaControllerMap.get(controllerId);
controller.increaseDeviceVolume(flags);
});
}
@Override
public void decreaseDeviceVolume(String controllerId) throws RemoteException {
runOnHandler(
@ -620,6 +640,16 @@ public class MediaControllerProviderService extends Service {
});
}
@Override
public void decreaseDeviceVolumeWithFlags(String controllerId, int flags)
throws RemoteException {
runOnHandler(
() -> {
MediaController controller = mediaControllerMap.get(controllerId);
controller.decreaseDeviceVolume(flags);
});
}
@Override
public void setDeviceMuted(String controllerId, boolean muted) throws RemoteException {
runOnHandler(
@ -629,6 +659,16 @@ public class MediaControllerProviderService extends Service {
});
}
@Override
public void setDeviceMutedWithFlags(String controllerId, boolean muted, int flags)
throws RemoteException {
runOnHandler(
() -> {
MediaController controller = mediaControllerMap.get(controllerId);
controller.setDeviceMuted(muted, flags);
});
}
@Override
public void release(String controllerId) throws RemoteException {
runOnHandler(

View File

@ -662,6 +662,46 @@ public class MediaSessionProviderService extends Service {
});
}
@Override
public void setDeviceVolume(String sessionId, int volume, int flags) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.setDeviceVolume(volume, flags);
});
}
@Override
public void decreaseDeviceVolume(String sessionId, int flags) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.decreaseDeviceVolume(flags);
});
}
@Override
public void increaseDeviceVolume(String sessionId, int flags) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.increaseDeviceVolume(flags);
});
}
@Override
public void setDeviceMuted(String sessionId, boolean muted, int flags) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.setDeviceMuted(muted, flags);
});
}
@Override
public void setCurrentAdIndexInAdGroup(String sessionId, int currentAdIndexInAdGroup)
throws RemoteException {
@ -874,7 +914,6 @@ public class MediaSessionProviderService extends Service {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.setVolume(volume);
player.notifyVolumeChanged();
});
}
@ -979,36 +1018,21 @@ public class MediaSessionProviderService extends Service {
}
@Override
public void notifyDeviceVolumeChanged(String sessionId, int volume, boolean muted)
throws RemoteException {
public void notifyVolumeChanged(String sessionId) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.deviceVolume = volume;
player.deviceMuted = muted;
player.notifyDeviceVolumeChanged();
player.notifyVolumeChanged();
});
}
@Override
public void decreaseDeviceVolume(String sessionId) throws RemoteException {
public void notifyDeviceVolumeChanged(String sessionId) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.decreaseDeviceVolume();
player.notifyDeviceVolumeChanged();
});
}
@Override
public void increaseDeviceVolume(String sessionId) throws RemoteException {
runOnHandler(
() -> {
MediaSession session = sessionMap.get(sessionId);
MockPlayer player = (MockPlayer) session.getPlayer();
player.increaseDeviceVolume();
player.notifyDeviceVolumeChanged();
});
}

View File

@ -68,7 +68,9 @@ public class MockPlayer implements Player {
METHOD_ADD_MEDIA_ITEMS_WITH_INDEX,
METHOD_CLEAR_MEDIA_ITEMS,
METHOD_DECREASE_DEVICE_VOLUME,
METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS,
METHOD_INCREASE_DEVICE_VOLUME,
METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS,
METHOD_MOVE_MEDIA_ITEM,
METHOD_MOVE_MEDIA_ITEMS,
METHOD_PAUSE,
@ -88,7 +90,9 @@ public class MockPlayer implements Player {
METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM,
METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX,
METHOD_SET_DEVICE_MUTED,
METHOD_SET_DEVICE_MUTED_WITH_FLAGS,
METHOD_SET_DEVICE_VOLUME,
METHOD_SET_DEVICE_VOLUME_WITH_FLAGS,
METHOD_SET_MEDIA_ITEM,
METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION,
METHOD_SET_MEDIA_ITEM_WITH_START_POSITION,
@ -191,6 +195,14 @@ public class MockPlayer implements Player {
public static final int METHOD_SET_VOLUME = 40;
/** Maps to {@link Player#stop()}. */
public static final int METHOD_STOP = 41;
/** Maps to {@link Player#decreaseDeviceVolume(int)}. */
public static final int METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS = 42;
/** Maps to {@link Player#increaseDeviceVolume(int)}. */
public static final int METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS = 43;
/** Maps to {@link Player#setDeviceMuted(boolean, int)}. */
public static final int METHOD_SET_DEVICE_MUTED_WITH_FLAGS = 44;
/** Maps to {@link Player#setDeviceVolume(int, int)}. */
public static final int METHOD_SET_DEVICE_VOLUME_WITH_FLAGS = 45;
private final boolean changePlayerStateWithTransportControl;
private final Looper applicationLooper;
@ -648,30 +660,58 @@ public class MockPlayer implements Player {
return deviceMuted;
}
@Deprecated
@Override
public void setDeviceVolume(int volume) {
deviceVolume = volume;
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_VOLUME)).open();
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
deviceVolume = volume;
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_VOLUME_WITH_FLAGS)).open();
}
@Deprecated
@Override
public void increaseDeviceVolume() {
deviceVolume += 1;
checkNotNull(conditionVariables.get(METHOD_INCREASE_DEVICE_VOLUME)).open();
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
deviceVolume += 1;
checkNotNull(conditionVariables.get(METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS)).open();
}
@Deprecated
@Override
public void decreaseDeviceVolume() {
deviceVolume -= 1;
checkNotNull(conditionVariables.get(METHOD_DECREASE_DEVICE_VOLUME)).open();
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
deviceVolume -= 1;
checkNotNull(conditionVariables.get(METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS)).open();
}
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
deviceMuted = muted;
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_MUTED)).open();
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
deviceMuted = muted;
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_MUTED_WITH_FLAGS)).open();
}
@Override
public void setPlayWhenReady(boolean playWhenReady) {
this.playWhenReady = playWhenReady;
@ -1329,7 +1369,9 @@ public class MockPlayer implements Player {
.put(METHOD_ADD_MEDIA_ITEMS_WITH_INDEX, new ConditionVariable())
.put(METHOD_CLEAR_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_DECREASE_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_DECREASE_DEVICE_VOLUME_WITH_FLAGS, new ConditionVariable())
.put(METHOD_INCREASE_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_INCREASE_DEVICE_VOLUME_WITH_FLAGS, new ConditionVariable())
.put(METHOD_MOVE_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_MOVE_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_PAUSE, new ConditionVariable())
@ -1349,7 +1391,9 @@ public class MockPlayer implements Player {
.put(METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX, new ConditionVariable())
.put(METHOD_SET_DEVICE_MUTED, new ConditionVariable())
.put(METHOD_SET_DEVICE_MUTED_WITH_FLAGS, new ConditionVariable())
.put(METHOD_SET_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_SET_DEVICE_VOLUME_WITH_FLAGS, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM_WITH_START_POSITION, new ConditionVariable())

View File

@ -29,6 +29,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackParameters;
@ -249,18 +250,34 @@ public class RemoteMediaController {
binder.setDeviceVolume(controllerId, volume);
}
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) throws RemoteException {
binder.setDeviceVolumeWithFlags(controllerId, volume, flags);
}
public void increaseDeviceVolume() throws RemoteException {
binder.increaseDeviceVolume(controllerId);
}
public void increaseDeviceVolume(@C.VolumeFlags int flags) throws RemoteException {
binder.increaseDeviceVolumeWithFlags(controllerId, flags);
}
public void decreaseDeviceVolume() throws RemoteException {
binder.decreaseDeviceVolume(controllerId);
}
public void decreaseDeviceVolume(@C.VolumeFlags int flags) throws RemoteException {
binder.decreaseDeviceVolumeWithFlags(controllerId, flags);
}
public void setDeviceMuted(boolean muted) throws RemoteException {
binder.setDeviceMuted(controllerId, muted);
}
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) throws RemoteException {
binder.setDeviceMutedWithFlags(controllerId, muted, flags);
}
public SessionResult sendCustomCommand(SessionCommand command, Bundle args)
throws RemoteException {
Bundle result = binder.sendCustomCommand(controllerId, command.toBundle(), args);

View File

@ -69,6 +69,7 @@ import android.os.RemoteException;
import android.support.v4.media.session.MediaSessionCompat;
import androidx.annotation.Nullable;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.C;
import androidx.media3.common.DeviceInfo;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.PlaybackException;
@ -90,8 +91,8 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* Represents remote {@link MediaSession} in the service app's MediaSessionProviderService. Users
* can run {@link MediaSession} methods remotely with this object.
* Represents remote {@link MediaSession} in the service app's {@link MediaSessionProviderService}.
* Users can run {@link MediaSession} methods remotely with this object.
*/
public class RemoteMediaSession {
private static final String TAG = "RemoteMediaSession";
@ -284,6 +285,22 @@ public class RemoteMediaSession {
binder.setVolume(sessionId, volume);
}
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) throws RemoteException {
binder.setDeviceVolume(sessionId, volume, flags);
}
public void decreaseDeviceVolume(@C.VolumeFlags int flags) throws RemoteException {
binder.decreaseDeviceVolume(sessionId, flags);
}
public void increaseDeviceVolume(@C.VolumeFlags int flags) throws RemoteException {
binder.increaseDeviceVolume(sessionId, flags);
}
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) throws RemoteException {
binder.setDeviceMuted(sessionId, muted, flags);
}
public void notifyPlayWhenReadyChanged(
boolean playWhenReady, @Player.PlaybackSuppressionReason int reason)
throws RemoteException {
@ -397,16 +414,12 @@ public class RemoteMediaSession {
return binder.surfaceExists(sessionId);
}
public void notifyDeviceVolumeChanged(int volume, boolean muted) throws RemoteException {
binder.notifyDeviceVolumeChanged(sessionId, volume, muted);
public void notifyDeviceVolumeChanged() throws RemoteException {
binder.notifyDeviceVolumeChanged(sessionId);
}
public void decreaseDeviceVolume() throws RemoteException {
binder.decreaseDeviceVolume(sessionId);
}
public void increaseDeviceVolume() throws RemoteException {
binder.increaseDeviceVolume(sessionId);
public void notifyVolumeChanged() throws RemoteException {
binder.notifyVolumeChanged(sessionId);
}
public void notifyCuesChanged(CueGroup cueGroup) throws RemoteException {

View File

@ -23,6 +23,7 @@ import android.view.TextureView;
import androidx.annotation.Nullable;
import androidx.media3.common.AudioAttributes;
import androidx.media3.common.BasePlayer;
import androidx.media3.common.C;
import androidx.media3.common.DeviceInfo;
import androidx.media3.common.MediaItem;
import androidx.media3.common.MediaMetadata;
@ -370,23 +371,59 @@ public class StubPlayer extends BasePlayer {
throw new UnsupportedOperationException();
}
/**
* @deprecated Use {@link #setDeviceVolume(int, int)} instead.
*/
@Deprecated
@Override
public void setDeviceVolume(int volume) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
throw new UnsupportedOperationException();
}
/**
* @deprecated Use {@link #increaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void increaseDeviceVolume() {
throw new UnsupportedOperationException();
}
@Override
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
throw new UnsupportedOperationException();
}
/**
* @deprecated Use {@link #decreaseDeviceVolume(int)} instead.
*/
@Deprecated
@Override
public void decreaseDeviceVolume() {
throw new UnsupportedOperationException();
}
@Override
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
throw new UnsupportedOperationException();
}
/**
* @deprecated Use {@link #setDeviceMuted(boolean, int)} instead.
*/
@Deprecated
@Override
public void setDeviceMuted(boolean muted) {
throw new UnsupportedOperationException();
}
@Override
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
throw new UnsupportedOperationException();
}
}