mirror of
https://github.com/androidx/media.git
synced 2025-05-07 07:30:22 +08:00
Allow ExoPlayer to opt into volume device control, forbidden by default
PiperOrigin-RevId: 532136692 (cherry picked from commit 1c6b894e8880480918babaf0a6f6b2038faf2e81)
This commit is contained in:
parent
7f1c1185e7
commit
27becc028d
@ -47,9 +47,17 @@
|
|||||||
objects that are dispatched by the dispatcher.
|
objects that are dispatched by the dispatcher.
|
||||||
* Rename `ExoTrackSelection.blacklist` to `excludeTrack` and
|
* Rename `ExoTrackSelection.blacklist` to `excludeTrack` and
|
||||||
`isBlacklisted` to `isTrackExcluded`.
|
`isBlacklisted` to `isTrackExcluded`.
|
||||||
* Deprecate `Player.COMMAND_GET_MEDIA_ITEMS_METADATA` and
|
* Add commands to Player:
|
||||||
`COMMAND_SET_MEDIA_ITEMS_METADATA`. Use `COMMAND_GET_METADATA` and
|
* `COMMAND_GET_METADATA`
|
||||||
`COMMAND_SET_PLAYLIST_METADATA` instead.
|
* `COMMAND_SET_PLAYLIST_METADATA`
|
||||||
|
* `COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS`
|
||||||
|
* `COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS`
|
||||||
|
* Add overloaded methods to Player which allow users to specify volume
|
||||||
|
flags:
|
||||||
|
* `void setDeviceVolume(int, int)`
|
||||||
|
* `void increaseDeviceVolume(int)`
|
||||||
|
* `void decreaseDeviceVolume(int)`
|
||||||
|
* `void setDeviceMuted(boolean, int)`
|
||||||
* Add `Buffer.isLastSample()` that denotes if `Buffer` contains flag
|
* Add `Buffer.isLastSample()` that denotes if `Buffer` contains flag
|
||||||
`C.BUFFER_FLAG_LAST_SAMPLE`.
|
`C.BUFFER_FLAG_LAST_SAMPLE`.
|
||||||
* Fix issue where last frame may not be rendered if the last sample with
|
* Fix issue where last frame may not be rendered if the last sample with
|
||||||
@ -64,13 +72,16 @@
|
|||||||
* Fix parsing of H.265 SPS in MPEG-TS files by re-using the parsing logic
|
* Fix parsing of H.265 SPS in MPEG-TS files by re-using the parsing logic
|
||||||
already used by RTSP and MP4 extractors
|
already used by RTSP and MP4 extractors
|
||||||
([#303](https://github.com/androidx/media/issues/303)).
|
([#303](https://github.com/androidx/media/issues/303)).
|
||||||
|
* ExoPlayer:
|
||||||
|
* Allow ExoPlayer to have control of device volume methods only if
|
||||||
|
explicitly opted in. Use
|
||||||
|
`ExoPlayer.Builder.setDeviceVolumeControlEnabled` to have access to:
|
||||||
|
* `getDeviceVolume()`
|
||||||
|
* `isDeviceMuted()`
|
||||||
|
* `setDeviceVolume(int)` and `setDeviceVolume(int, int)`
|
||||||
|
* `increaseDeviceVolume(int)` and `increaseDeviceVolume(int, int)`
|
||||||
|
* `decreaseDeviceVolume(int)` and `decreaseDeviceVolume(int, int)`
|
||||||
* Session:
|
* Session:
|
||||||
* 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)`
|
|
||||||
* Fix issue where `MediaController` doesn't update its available commands
|
* Fix issue where `MediaController` doesn't update its available commands
|
||||||
when connected to a legacy `MediaSessionCompat` that updates its
|
when connected to a legacy `MediaSessionCompat` that updates its
|
||||||
actions.
|
actions.
|
||||||
|
@ -479,6 +479,7 @@ public interface ExoPlayer extends Player {
|
|||||||
@C.WakeMode /* package */ int wakeMode;
|
@C.WakeMode /* package */ int wakeMode;
|
||||||
/* package */ boolean handleAudioBecomingNoisy;
|
/* package */ boolean handleAudioBecomingNoisy;
|
||||||
/* package */ boolean skipSilenceEnabled;
|
/* package */ boolean skipSilenceEnabled;
|
||||||
|
/* package */ boolean deviceVolumeControlEnabled;
|
||||||
@C.VideoScalingMode /* package */ int videoScalingMode;
|
@C.VideoScalingMode /* package */ int videoScalingMode;
|
||||||
@C.VideoChangeFrameRateStrategy /* package */ int videoChangeFrameRateStrategy;
|
@C.VideoChangeFrameRateStrategy /* package */ int videoChangeFrameRateStrategy;
|
||||||
/* package */ boolean useLazyPreparation;
|
/* package */ boolean useLazyPreparation;
|
||||||
@ -918,6 +919,21 @@ public interface ExoPlayer extends Player {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the player is allowed to set, increase, decrease or mute device volume.
|
||||||
|
*
|
||||||
|
* @param deviceVolumeControlEnabled Whether controlling device volume is enabled.
|
||||||
|
* @return This builder.
|
||||||
|
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
@UnstableApi
|
||||||
|
public Builder setDeviceVolumeControlEnabled(boolean deviceVolumeControlEnabled) {
|
||||||
|
checkState(!buildCalled);
|
||||||
|
this.deviceVolumeControlEnabled = deviceVolumeControlEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link C.VideoScalingMode} that will be used by the player.
|
* Sets the {@link C.VideoScalingMode} that will be used by the player.
|
||||||
*
|
*
|
||||||
|
@ -168,7 +168,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
private final FrameMetadataListener frameMetadataListener;
|
private final FrameMetadataListener frameMetadataListener;
|
||||||
private final AudioBecomingNoisyManager audioBecomingNoisyManager;
|
private final AudioBecomingNoisyManager audioBecomingNoisyManager;
|
||||||
private final AudioFocusManager audioFocusManager;
|
private final AudioFocusManager audioFocusManager;
|
||||||
private final StreamVolumeManager streamVolumeManager;
|
@Nullable private final StreamVolumeManager streamVolumeManager;
|
||||||
private final WakeLockManager wakeLockManager;
|
private final WakeLockManager wakeLockManager;
|
||||||
private final WifiLockManager wifiLockManager;
|
private final WifiLockManager wifiLockManager;
|
||||||
private final long detachSurfaceTimeoutMs;
|
private final long detachSurfaceTimeoutMs;
|
||||||
@ -228,6 +228,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
private long maskingWindowPositionMs;
|
private long maskingWindowPositionMs;
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak")
|
@SuppressLint("HandlerLeak")
|
||||||
|
@SuppressWarnings("deprecation") // Control flow for old volume commands
|
||||||
public ExoPlayerImpl(ExoPlayer.Builder builder, @Nullable Player wrappingPlayer) {
|
public ExoPlayerImpl(ExoPlayer.Builder builder, @Nullable Player wrappingPlayer) {
|
||||||
constructorFinished = new ConditionVariable();
|
constructorFinished = new ConditionVariable();
|
||||||
try {
|
try {
|
||||||
@ -306,17 +307,17 @@ import java.util.concurrent.TimeoutException;
|
|||||||
COMMAND_GET_TRACKS,
|
COMMAND_GET_TRACKS,
|
||||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||||
COMMAND_GET_VOLUME,
|
COMMAND_GET_VOLUME,
|
||||||
COMMAND_GET_DEVICE_VOLUME,
|
|
||||||
COMMAND_SET_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_SET_VIDEO_SURFACE,
|
||||||
COMMAND_GET_TEXT,
|
COMMAND_GET_TEXT,
|
||||||
COMMAND_RELEASE)
|
COMMAND_RELEASE)
|
||||||
.addIf(
|
.addIf(
|
||||||
COMMAND_SET_TRACK_SELECTION_PARAMETERS, trackSelector.isSetParametersSupported())
|
COMMAND_SET_TRACK_SELECTION_PARAMETERS, trackSelector.isSetParametersSupported())
|
||||||
|
.addIf(COMMAND_GET_DEVICE_VOLUME, builder.deviceVolumeControlEnabled)
|
||||||
|
.addIf(COMMAND_SET_DEVICE_VOLUME, builder.deviceVolumeControlEnabled)
|
||||||
|
.addIf(COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS, builder.deviceVolumeControlEnabled)
|
||||||
|
.addIf(COMMAND_ADJUST_DEVICE_VOLUME, builder.deviceVolumeControlEnabled)
|
||||||
|
.addIf(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS, builder.deviceVolumeControlEnabled)
|
||||||
.build();
|
.build();
|
||||||
availableCommands =
|
availableCommands =
|
||||||
new Commands.Builder()
|
new Commands.Builder()
|
||||||
@ -381,9 +382,13 @@ import java.util.concurrent.TimeoutException;
|
|||||||
audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy);
|
audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy);
|
||||||
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
|
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
|
||||||
audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null);
|
audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null);
|
||||||
streamVolumeManager =
|
if (builder.deviceVolumeControlEnabled) {
|
||||||
new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
streamVolumeManager =
|
||||||
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
|
new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
||||||
|
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
|
||||||
|
} else {
|
||||||
|
streamVolumeManager = null;
|
||||||
|
}
|
||||||
wakeLockManager = new WakeLockManager(builder.context);
|
wakeLockManager = new WakeLockManager(builder.context);
|
||||||
wakeLockManager.setEnabled(builder.wakeMode != C.WAKE_MODE_NONE);
|
wakeLockManager.setEnabled(builder.wakeMode != C.WAKE_MODE_NONE);
|
||||||
wifiLockManager = new WifiLockManager(builder.context);
|
wifiLockManager = new WifiLockManager(builder.context);
|
||||||
@ -999,7 +1004,9 @@ import java.util.concurrent.TimeoutException;
|
|||||||
keepSessionIdAudioTrack = null;
|
keepSessionIdAudioTrack = null;
|
||||||
}
|
}
|
||||||
audioBecomingNoisyManager.setEnabled(false);
|
audioBecomingNoisyManager.setEnabled(false);
|
||||||
streamVolumeManager.release();
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.release();
|
||||||
|
}
|
||||||
wakeLockManager.setStayAwake(false);
|
wakeLockManager.setStayAwake(false);
|
||||||
wifiLockManager.setStayAwake(false);
|
wifiLockManager.setStayAwake(false);
|
||||||
audioFocusManager.release();
|
audioFocusManager.release();
|
||||||
@ -1421,7 +1428,10 @@ import java.util.concurrent.TimeoutException;
|
|||||||
if (!Util.areEqual(this.audioAttributes, newAudioAttributes)) {
|
if (!Util.areEqual(this.audioAttributes, newAudioAttributes)) {
|
||||||
this.audioAttributes = newAudioAttributes;
|
this.audioAttributes = newAudioAttributes;
|
||||||
sendRendererMessage(TRACK_TYPE_AUDIO, MSG_SET_AUDIO_ATTRIBUTES, newAudioAttributes);
|
sendRendererMessage(TRACK_TYPE_AUDIO, MSG_SET_AUDIO_ATTRIBUTES, newAudioAttributes);
|
||||||
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(newAudioAttributes.usage));
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.setStreamType(
|
||||||
|
Util.getStreamTypeForAudioUsage(newAudioAttributes.usage));
|
||||||
|
}
|
||||||
// Queue event only and flush after updating playWhenReady in case both events are triggered.
|
// Queue event only and flush after updating playWhenReady in case both events are triggered.
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
EVENT_AUDIO_ATTRIBUTES_CHANGED,
|
EVENT_AUDIO_ATTRIBUTES_CHANGED,
|
||||||
@ -1703,13 +1713,21 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public int getDeviceVolume() {
|
public int getDeviceVolume() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
return streamVolumeManager.getVolume();
|
if (streamVolumeManager != null) {
|
||||||
|
return streamVolumeManager.getVolume();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDeviceMuted() {
|
public boolean isDeviceMuted() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
return streamVolumeManager.isMuted();
|
if (streamVolumeManager != null) {
|
||||||
|
return streamVolumeManager.isMuted();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1719,13 +1737,17 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public void setDeviceVolume(int volume) {
|
public void setDeviceVolume(int volume) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.setVolume(volume, C.VOLUME_FLAG_SHOW_UI);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.setVolume(volume, C.VOLUME_FLAG_SHOW_UI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
|
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.setVolume(volume, flags);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.setVolume(volume, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1735,13 +1757,17 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public void increaseDeviceVolume() {
|
public void increaseDeviceVolume() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.increaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.increaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
|
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.increaseVolume(flags);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.increaseVolume(flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1751,13 +1777,17 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public void decreaseDeviceVolume() {
|
public void decreaseDeviceVolume() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.decreaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.decreaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
|
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.decreaseVolume(flags);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.decreaseVolume(flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1767,13 +1797,17 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public void setDeviceMuted(boolean muted) {
|
public void setDeviceMuted(boolean muted) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.setMuted(muted, C.VOLUME_FLAG_SHOW_UI);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.setMuted(muted, C.VOLUME_FLAG_SHOW_UI);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
|
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
streamVolumeManager.setMuted(muted, flags);
|
if (streamVolumeManager != null) {
|
||||||
|
streamVolumeManager.setMuted(muted, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2797,10 +2831,10 @@ import java.util.concurrent.TimeoutException;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DeviceInfo createDeviceInfo(StreamVolumeManager streamVolumeManager) {
|
private static DeviceInfo createDeviceInfo(@Nullable StreamVolumeManager streamVolumeManager) {
|
||||||
return new DeviceInfo.Builder(DeviceInfo.PLAYBACK_TYPE_LOCAL)
|
return new DeviceInfo.Builder(DeviceInfo.PLAYBACK_TYPE_LOCAL)
|
||||||
.setMinVolume(streamVolumeManager.getMinVolume())
|
.setMinVolume(streamVolumeManager != null ? streamVolumeManager.getMinVolume() : 0)
|
||||||
.setMaxVolume(streamVolumeManager.getMaxVolume())
|
.setMaxVolume(streamVolumeManager != null ? streamVolumeManager.getMaxVolume() : 0)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.media3.common.AdPlaybackState;
|
import androidx.media3.common.AdPlaybackState;
|
||||||
import androidx.media3.common.AudioAttributes;
|
import androidx.media3.common.AudioAttributes;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
|
import androidx.media3.common.DeviceInfo;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
@ -9155,6 +9156,7 @@ public final class ExoPlayerTest {
|
|||||||
player.release();
|
player.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Checking old volume commands
|
||||||
@Test
|
@Test
|
||||||
public void isCommandAvailable_isTrueForAvailableCommands() {
|
public void isCommandAvailable_isTrueForAvailableCommands() {
|
||||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||||
@ -9184,10 +9186,7 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(player.isCommandAvailable(COMMAND_SET_MEDIA_ITEM)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_SET_MEDIA_ITEM)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_GET_VOLUME)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_GET_VOLUME)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_GET_DEVICE_VOLUME)).isTrue();
|
|
||||||
assertThat(player.isCommandAvailable(COMMAND_SET_VOLUME)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_SET_VOLUME)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_SET_DEVICE_VOLUME)).isTrue();
|
|
||||||
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)).isTrue();
|
|
||||||
assertThat(player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_GET_TEXT)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_GET_TEXT)).isTrue();
|
||||||
assertThat(player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)).isTrue();
|
||||||
@ -9195,6 +9194,33 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(player.isCommandAvailable(COMMAND_RELEASE)).isTrue();
|
assertThat(player.isCommandAvailable(COMMAND_RELEASE)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Checking old volume commands
|
||||||
|
@Test
|
||||||
|
public void isCommandAvailable_withDeviceVolumeControlEnabled_isTrueForDeviceVolumeCommands() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(context).setDeviceVolumeControlEnabled(true).build();
|
||||||
|
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_GET_DEVICE_VOLUME)).isTrue();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_SET_DEVICE_VOLUME)).isTrue();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)).isTrue();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)).isTrue();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Checking old volume commands
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
isCommandAvailable_withoutDeviceVolumeControlEnabled_isFalseForDeviceVolumeCommands() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(context).setDeviceVolumeControlEnabled(false).build();
|
||||||
|
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_GET_DEVICE_VOLUME)).isFalse();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_SET_DEVICE_VOLUME)).isFalse();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)).isFalse();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS)).isFalse();
|
||||||
|
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isCommandAvailable_duringAd_isFalseForSeekCommands() throws Exception {
|
public void isCommandAvailable_duringAd_isFalseForSeekCommands() throws Exception {
|
||||||
AdPlaybackState adPlaybackState =
|
AdPlaybackState adPlaybackState =
|
||||||
@ -9529,7 +9555,9 @@ public final class ExoPlayerTest {
|
|||||||
Player.Commands defaultCommands = createWithDefaultCommands();
|
Player.Commands defaultCommands = createWithDefaultCommands();
|
||||||
Player.Commands commandsWithSeekToNextWindow =
|
Player.Commands commandsWithSeekToNextWindow =
|
||||||
createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT);
|
createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT);
|
||||||
Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty= */ true);
|
Player.Commands emptyTimelineCommands =
|
||||||
|
createWithDefaultCommands(
|
||||||
|
/* isTimelineEmpty= */ true, /* allowDeviceVolumeControl= */ false);
|
||||||
Player.Listener mockListener = mock(Player.Listener.class);
|
Player.Listener mockListener = mock(Player.Listener.class);
|
||||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||||
player.addListener(mockListener);
|
player.addListener(mockListener);
|
||||||
@ -9557,7 +9585,9 @@ public final class ExoPlayerTest {
|
|||||||
Player.Commands defaultCommands = createWithDefaultCommands();
|
Player.Commands defaultCommands = createWithDefaultCommands();
|
||||||
Player.Commands commandsWithSeekToPreviousWindow =
|
Player.Commands commandsWithSeekToPreviousWindow =
|
||||||
createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
|
createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
|
||||||
Player.Commands emptyTimelineCommands = createWithDefaultCommands(/* isTimelineEmpty= */ true);
|
Player.Commands emptyTimelineCommands =
|
||||||
|
createWithDefaultCommands(
|
||||||
|
/* isTimelineEmpty= */ true, /* allowDeviceVolumeControl= */ false);
|
||||||
Player.Listener mockListener = mock(Player.Listener.class);
|
Player.Listener mockListener = mock(Player.Listener.class);
|
||||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||||
player.addListener(mockListener);
|
player.addListener(mockListener);
|
||||||
@ -12323,7 +12353,9 @@ public final class ExoPlayerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void releaseAfterVolumeChanges_triggerPendingDeviceVolumeEventsInListener() {
|
public void releaseAfterVolumeChanges_triggerPendingDeviceVolumeEventsInListener() {
|
||||||
ExoPlayer player =
|
ExoPlayer player =
|
||||||
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build();
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(true)
|
||||||
|
.build();
|
||||||
Player.Listener listener = mock(Player.Listener.class);
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
player.addListener(listener);
|
player.addListener(listener);
|
||||||
|
|
||||||
@ -12343,6 +12375,113 @@ public final class ExoPlayerTest {
|
|||||||
verify(listener, atLeast(2)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
verify(listener, atLeast(2)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDeviceMutedWithoutDeviceVolumeControl_noEffectDeviceRemainsUnmuted() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(false)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.setDeviceMuted(/* muted= */ true, /* flags= */ 0); // no volume control, no effect
|
||||||
|
boolean isActuallyMuted = player.isDeviceMuted();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
assertThat(isActuallyMuted).isFalse();
|
||||||
|
verify(listener, times(0)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDeviceMutedWithDeviceVolumeControl_deviceGetsMuted() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(true)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.setDeviceMuted(/* muted= */ true, /* flags= */ 0);
|
||||||
|
boolean isActuallyMuted = player.isDeviceMuted();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
assertThat(isActuallyMuted).isTrue();
|
||||||
|
verify(listener).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void increaseDeviceVolumeWithoutDeviceVolumeControl_deviceVolumeUnchanged() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(false)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.increaseDeviceVolume(/* flags= */ 0); // no volume control, no effect
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
verify(listener, times(0)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decreaseDeviceVolumeWithoutDeviceVolumeControl_deviceVolumeUnchanged() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(false)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
player.decreaseDeviceVolume(/* flags= */ 0); // no volume control, no effect
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
verify(listener, times(0)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDeviceVolumeWithoutDeviceVolumeControl_returnsZero() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(false)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
int initialDeviceVolume = player.getDeviceVolume();
|
||||||
|
player.setDeviceVolume(10, /* flags= */ 0);
|
||||||
|
int setDeviceVolumeAt10 = player.getDeviceVolume();
|
||||||
|
player.increaseDeviceVolume(/* flags= */ 0);
|
||||||
|
player.increaseDeviceVolume(/* flags= */ 0);
|
||||||
|
int setDeviceVolumeAt12 = player.getDeviceVolume();
|
||||||
|
player.decreaseDeviceVolume(/* flags= */ 0);
|
||||||
|
int setDeviceVolumeAt11 = player.getDeviceVolume();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
assertThat(initialDeviceVolume).isEqualTo(0);
|
||||||
|
assertThat(setDeviceVolumeAt10).isEqualTo(0);
|
||||||
|
assertThat(setDeviceVolumeAt12).isEqualTo(0);
|
||||||
|
assertThat(setDeviceVolumeAt11).isEqualTo(0);
|
||||||
|
verify(listener, times(0)).onDeviceVolumeChanged(anyInt(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDeviceInfoWithoutDeviceVolumeControl_returnsZeroForMinMaxVolume() {
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||||
|
.setDeviceVolumeControlEnabled(false)
|
||||||
|
.build();
|
||||||
|
Player.Listener listener = mock(Player.Listener.class);
|
||||||
|
player.addListener(listener);
|
||||||
|
|
||||||
|
DeviceInfo deviceInfo = player.getDeviceInfo();
|
||||||
|
int minVolume = deviceInfo.minVolume;
|
||||||
|
int maxVolume = deviceInfo.maxVolume;
|
||||||
|
|
||||||
|
assertThat(minVolume).isEqualTo(0);
|
||||||
|
assertThat(maxVolume).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadControlBackBuffer_withInsufficientMemoryLimits_stillContinuesPlayback()
|
public void loadControlBackBuffer_withInsufficientMemoryLimits_stillContinuesPlayback()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@ -12482,8 +12621,11 @@ public final class ExoPlayerTest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Control flow for the old volume commands
|
||||||
private static Player.Commands createWithDefaultCommands(
|
private static Player.Commands createWithDefaultCommands(
|
||||||
boolean isTimelineEmpty, @Player.Command int... additionalCommands) {
|
boolean isTimelineEmpty,
|
||||||
|
boolean allowDeviceVolumeControl,
|
||||||
|
@Player.Command int... additionalCommands) {
|
||||||
Player.Commands.Builder builder = new Player.Commands.Builder();
|
Player.Commands.Builder builder = new Player.Commands.Builder();
|
||||||
builder.addAll(
|
builder.addAll(
|
||||||
COMMAND_PLAY_PAUSE,
|
COMMAND_PLAY_PAUSE,
|
||||||
@ -12502,12 +12644,7 @@ public final class ExoPlayerTest {
|
|||||||
COMMAND_SET_MEDIA_ITEM,
|
COMMAND_SET_MEDIA_ITEM,
|
||||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||||
COMMAND_GET_VOLUME,
|
COMMAND_GET_VOLUME,
|
||||||
COMMAND_GET_DEVICE_VOLUME,
|
|
||||||
COMMAND_SET_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_SET_VIDEO_SURFACE,
|
||||||
COMMAND_GET_TEXT,
|
COMMAND_GET_TEXT,
|
||||||
COMMAND_SET_TRACK_SELECTION_PARAMETERS,
|
COMMAND_SET_TRACK_SELECTION_PARAMETERS,
|
||||||
@ -12516,13 +12653,22 @@ public final class ExoPlayerTest {
|
|||||||
if (!isTimelineEmpty) {
|
if (!isTimelineEmpty) {
|
||||||
builder.add(COMMAND_SEEK_TO_PREVIOUS);
|
builder.add(COMMAND_SEEK_TO_PREVIOUS);
|
||||||
}
|
}
|
||||||
|
if (allowDeviceVolumeControl) {
|
||||||
|
builder.addAll(
|
||||||
|
COMMAND_GET_DEVICE_VOLUME,
|
||||||
|
COMMAND_SET_DEVICE_VOLUME,
|
||||||
|
COMMAND_SET_DEVICE_VOLUME_WITH_FLAGS,
|
||||||
|
COMMAND_ADJUST_DEVICE_VOLUME,
|
||||||
|
COMMAND_ADJUST_DEVICE_VOLUME_WITH_FLAGS);
|
||||||
|
}
|
||||||
builder.addAll(additionalCommands);
|
builder.addAll(additionalCommands);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Player.Commands createWithDefaultCommands(
|
private static Player.Commands createWithDefaultCommands(
|
||||||
@Player.Command int... additionalCommands) {
|
@Player.Command int... additionalCommands) {
|
||||||
return createWithDefaultCommands(/* isTimelineEmpty= */ false, additionalCommands);
|
return createWithDefaultCommands(
|
||||||
|
/* isTimelineEmpty= */ false, /* allowDeviceVolumeControl= */ false, additionalCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal classes.
|
// Internal classes.
|
||||||
|
@ -54,6 +54,7 @@ public class TestExoPlayerBuilder {
|
|||||||
private @MonotonicNonNull Looper looper;
|
private @MonotonicNonNull Looper looper;
|
||||||
private long seekBackIncrementMs;
|
private long seekBackIncrementMs;
|
||||||
private long seekForwardIncrementMs;
|
private long seekForwardIncrementMs;
|
||||||
|
private boolean deviceVolumeControlEnabled;
|
||||||
|
|
||||||
public TestExoPlayerBuilder(Context context) {
|
public TestExoPlayerBuilder(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -67,6 +68,7 @@ public class TestExoPlayerBuilder {
|
|||||||
}
|
}
|
||||||
seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS;
|
seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS;
|
||||||
seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS;
|
seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS;
|
||||||
|
deviceVolumeControlEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,6 +284,18 @@ public class TestExoPlayerBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the variable controlling player's ability to get/set device volume.
|
||||||
|
*
|
||||||
|
* @param deviceVolumeControlEnabled Whether the player can get/set device volume.
|
||||||
|
* @return This builder.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public TestExoPlayerBuilder setDeviceVolumeControlEnabled(boolean deviceVolumeControlEnabled) {
|
||||||
|
this.deviceVolumeControlEnabled = deviceVolumeControlEnabled;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the seek forward increment used by the player. */
|
/** Returns the seek forward increment used by the player. */
|
||||||
public long getSeekForwardIncrementMs() {
|
public long getSeekForwardIncrementMs() {
|
||||||
return seekForwardIncrementMs;
|
return seekForwardIncrementMs;
|
||||||
@ -322,7 +336,8 @@ public class TestExoPlayerBuilder {
|
|||||||
.setUseLazyPreparation(useLazyPreparation)
|
.setUseLazyPreparation(useLazyPreparation)
|
||||||
.setLooper(looper)
|
.setLooper(looper)
|
||||||
.setSeekBackIncrementMs(seekBackIncrementMs)
|
.setSeekBackIncrementMs(seekBackIncrementMs)
|
||||||
.setSeekForwardIncrementMs(seekForwardIncrementMs);
|
.setSeekForwardIncrementMs(seekForwardIncrementMs)
|
||||||
|
.setDeviceVolumeControlEnabled(deviceVolumeControlEnabled);
|
||||||
if (mediaSourceFactory != null) {
|
if (mediaSourceFactory != null) {
|
||||||
builder.setMediaSourceFactory(mediaSourceFactory);
|
builder.setMediaSourceFactory(mediaSourceFactory);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user