mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +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.
|
||||
* Rename `ExoTrackSelection.blacklist` to `excludeTrack` and
|
||||
`isBlacklisted` to `isTrackExcluded`.
|
||||
* Deprecate `Player.COMMAND_GET_MEDIA_ITEMS_METADATA` and
|
||||
`COMMAND_SET_MEDIA_ITEMS_METADATA`. Use `COMMAND_GET_METADATA` and
|
||||
`COMMAND_SET_PLAYLIST_METADATA` instead.
|
||||
* Add commands to Player:
|
||||
* `COMMAND_GET_METADATA`
|
||||
* `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
|
||||
`C.BUFFER_FLAG_LAST_SAMPLE`.
|
||||
* 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
|
||||
already used by RTSP and MP4 extractors
|
||||
([#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:
|
||||
* 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
|
||||
when connected to a legacy `MediaSessionCompat` that updates its
|
||||
actions.
|
||||
|
@ -479,6 +479,7 @@ public interface ExoPlayer extends Player {
|
||||
@C.WakeMode /* package */ int wakeMode;
|
||||
/* package */ boolean handleAudioBecomingNoisy;
|
||||
/* package */ boolean skipSilenceEnabled;
|
||||
/* package */ boolean deviceVolumeControlEnabled;
|
||||
@C.VideoScalingMode /* package */ int videoScalingMode;
|
||||
@C.VideoChangeFrameRateStrategy /* package */ int videoChangeFrameRateStrategy;
|
||||
/* package */ boolean useLazyPreparation;
|
||||
@ -918,6 +919,21 @@ public interface ExoPlayer extends Player {
|
||||
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.
|
||||
*
|
||||
|
@ -168,7 +168,7 @@ import java.util.concurrent.TimeoutException;
|
||||
private final FrameMetadataListener frameMetadataListener;
|
||||
private final AudioBecomingNoisyManager audioBecomingNoisyManager;
|
||||
private final AudioFocusManager audioFocusManager;
|
||||
private final StreamVolumeManager streamVolumeManager;
|
||||
@Nullable private final StreamVolumeManager streamVolumeManager;
|
||||
private final WakeLockManager wakeLockManager;
|
||||
private final WifiLockManager wifiLockManager;
|
||||
private final long detachSurfaceTimeoutMs;
|
||||
@ -228,6 +228,7 @@ import java.util.concurrent.TimeoutException;
|
||||
private long maskingWindowPositionMs;
|
||||
|
||||
@SuppressLint("HandlerLeak")
|
||||
@SuppressWarnings("deprecation") // Control flow for old volume commands
|
||||
public ExoPlayerImpl(ExoPlayer.Builder builder, @Nullable Player wrappingPlayer) {
|
||||
constructorFinished = new ConditionVariable();
|
||||
try {
|
||||
@ -306,17 +307,17 @@ import java.util.concurrent.TimeoutException;
|
||||
COMMAND_GET_TRACKS,
|
||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
COMMAND_GET_VOLUME,
|
||||
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)
|
||||
.addIf(
|
||||
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();
|
||||
availableCommands =
|
||||
new Commands.Builder()
|
||||
@ -381,9 +382,13 @@ import java.util.concurrent.TimeoutException;
|
||||
audioBecomingNoisyManager.setEnabled(builder.handleAudioBecomingNoisy);
|
||||
audioFocusManager = new AudioFocusManager(builder.context, eventHandler, componentListener);
|
||||
audioFocusManager.setAudioAttributes(builder.handleAudioFocus ? audioAttributes : null);
|
||||
streamVolumeManager =
|
||||
new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
||||
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
|
||||
if (builder.deviceVolumeControlEnabled) {
|
||||
streamVolumeManager =
|
||||
new StreamVolumeManager(builder.context, eventHandler, componentListener);
|
||||
streamVolumeManager.setStreamType(Util.getStreamTypeForAudioUsage(audioAttributes.usage));
|
||||
} else {
|
||||
streamVolumeManager = null;
|
||||
}
|
||||
wakeLockManager = new WakeLockManager(builder.context);
|
||||
wakeLockManager.setEnabled(builder.wakeMode != C.WAKE_MODE_NONE);
|
||||
wifiLockManager = new WifiLockManager(builder.context);
|
||||
@ -999,7 +1004,9 @@ import java.util.concurrent.TimeoutException;
|
||||
keepSessionIdAudioTrack = null;
|
||||
}
|
||||
audioBecomingNoisyManager.setEnabled(false);
|
||||
streamVolumeManager.release();
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.release();
|
||||
}
|
||||
wakeLockManager.setStayAwake(false);
|
||||
wifiLockManager.setStayAwake(false);
|
||||
audioFocusManager.release();
|
||||
@ -1421,7 +1428,10 @@ import java.util.concurrent.TimeoutException;
|
||||
if (!Util.areEqual(this.audioAttributes, newAudioAttributes)) {
|
||||
this.audioAttributes = 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.
|
||||
listeners.queueEvent(
|
||||
EVENT_AUDIO_ATTRIBUTES_CHANGED,
|
||||
@ -1703,13 +1713,21 @@ import java.util.concurrent.TimeoutException;
|
||||
@Override
|
||||
public int getDeviceVolume() {
|
||||
verifyApplicationThread();
|
||||
return streamVolumeManager.getVolume();
|
||||
if (streamVolumeManager != null) {
|
||||
return streamVolumeManager.getVolume();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceMuted() {
|
||||
verifyApplicationThread();
|
||||
return streamVolumeManager.isMuted();
|
||||
if (streamVolumeManager != null) {
|
||||
return streamVolumeManager.isMuted();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1719,13 +1737,17 @@ import java.util.concurrent.TimeoutException;
|
||||
@Override
|
||||
public void setDeviceVolume(int volume) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.setVolume(volume, C.VOLUME_FLAG_SHOW_UI);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.setVolume(volume, C.VOLUME_FLAG_SHOW_UI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceVolume(int volume, @C.VolumeFlags int flags) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.setVolume(volume, flags);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.setVolume(volume, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1735,13 +1757,17 @@ import java.util.concurrent.TimeoutException;
|
||||
@Override
|
||||
public void increaseDeviceVolume() {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.increaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.increaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increaseDeviceVolume(@C.VolumeFlags int flags) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.increaseVolume(flags);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.increaseVolume(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1751,13 +1777,17 @@ import java.util.concurrent.TimeoutException;
|
||||
@Override
|
||||
public void decreaseDeviceVolume() {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.decreaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.decreaseVolume(C.VOLUME_FLAG_SHOW_UI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decreaseDeviceVolume(@C.VolumeFlags int flags) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.decreaseVolume(flags);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.decreaseVolume(flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1767,13 +1797,17 @@ import java.util.concurrent.TimeoutException;
|
||||
@Override
|
||||
public void setDeviceMuted(boolean muted) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.setMuted(muted, C.VOLUME_FLAG_SHOW_UI);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.setMuted(muted, C.VOLUME_FLAG_SHOW_UI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceMuted(boolean muted, @C.VolumeFlags int flags) {
|
||||
verifyApplicationThread();
|
||||
streamVolumeManager.setMuted(muted, flags);
|
||||
if (streamVolumeManager != null) {
|
||||
streamVolumeManager.setMuted(muted, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
.setMinVolume(streamVolumeManager.getMinVolume())
|
||||
.setMaxVolume(streamVolumeManager.getMaxVolume())
|
||||
.setMinVolume(streamVolumeManager != null ? streamVolumeManager.getMinVolume() : 0)
|
||||
.setMaxVolume(streamVolumeManager != null ? streamVolumeManager.getMaxVolume() : 0)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -100,6 +100,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.AdPlaybackState;
|
||||
import androidx.media3.common.AudioAttributes;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.DeviceInfo;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.MediaMetadata;
|
||||
@ -9155,6 +9156,7 @@ public final class ExoPlayerTest {
|
||||
player.release();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Checking old volume commands
|
||||
@Test
|
||||
public void isCommandAvailable_isTrueForAvailableCommands() {
|
||||
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_GET_AUDIO_ATTRIBUTES)).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_DEVICE_VOLUME)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_ADJUST_DEVICE_VOLUME)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_SET_VIDEO_SURFACE)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_GET_TEXT)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)).isTrue();
|
||||
@ -9195,6 +9194,33 @@ public final class ExoPlayerTest {
|
||||
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
|
||||
public void isCommandAvailable_duringAd_isFalseForSeekCommands() throws Exception {
|
||||
AdPlaybackState adPlaybackState =
|
||||
@ -9529,7 +9555,9 @@ public final class ExoPlayerTest {
|
||||
Player.Commands defaultCommands = createWithDefaultCommands();
|
||||
Player.Commands commandsWithSeekToNextWindow =
|
||||
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);
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
player.addListener(mockListener);
|
||||
@ -9557,7 +9585,9 @@ public final class ExoPlayerTest {
|
||||
Player.Commands defaultCommands = createWithDefaultCommands();
|
||||
Player.Commands commandsWithSeekToPreviousWindow =
|
||||
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);
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
player.addListener(mockListener);
|
||||
@ -12323,7 +12353,9 @@ public final class ExoPlayerTest {
|
||||
@Test
|
||||
public void releaseAfterVolumeChanges_triggerPendingDeviceVolumeEventsInListener() {
|
||||
ExoPlayer player =
|
||||
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build();
|
||||
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext())
|
||||
.setDeviceVolumeControlEnabled(true)
|
||||
.build();
|
||||
Player.Listener listener = mock(Player.Listener.class);
|
||||
player.addListener(listener);
|
||||
|
||||
@ -12343,6 +12375,113 @@ public final class ExoPlayerTest {
|
||||
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
|
||||
public void loadControlBackBuffer_withInsufficientMemoryLimits_stillContinuesPlayback()
|
||||
throws Exception {
|
||||
@ -12482,8 +12621,11 @@ public final class ExoPlayerTest {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // Control flow for the old volume commands
|
||||
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();
|
||||
builder.addAll(
|
||||
COMMAND_PLAY_PAUSE,
|
||||
@ -12502,12 +12644,7 @@ public final class ExoPlayerTest {
|
||||
COMMAND_SET_MEDIA_ITEM,
|
||||
COMMAND_GET_AUDIO_ATTRIBUTES,
|
||||
COMMAND_GET_VOLUME,
|
||||
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,
|
||||
@ -12516,13 +12653,22 @@ public final class ExoPlayerTest {
|
||||
if (!isTimelineEmpty) {
|
||||
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);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Player.Commands createWithDefaultCommands(
|
||||
@Player.Command int... additionalCommands) {
|
||||
return createWithDefaultCommands(/* isTimelineEmpty= */ false, additionalCommands);
|
||||
return createWithDefaultCommands(
|
||||
/* isTimelineEmpty= */ false, /* allowDeviceVolumeControl= */ false, additionalCommands);
|
||||
}
|
||||
|
||||
// Internal classes.
|
||||
|
@ -54,6 +54,7 @@ public class TestExoPlayerBuilder {
|
||||
private @MonotonicNonNull Looper looper;
|
||||
private long seekBackIncrementMs;
|
||||
private long seekForwardIncrementMs;
|
||||
private boolean deviceVolumeControlEnabled;
|
||||
|
||||
public TestExoPlayerBuilder(Context context) {
|
||||
this.context = context;
|
||||
@ -67,6 +68,7 @@ public class TestExoPlayerBuilder {
|
||||
}
|
||||
seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS;
|
||||
seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS;
|
||||
deviceVolumeControlEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,6 +284,18 @@ public class TestExoPlayerBuilder {
|
||||
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. */
|
||||
public long getSeekForwardIncrementMs() {
|
||||
return seekForwardIncrementMs;
|
||||
@ -322,7 +336,8 @@ public class TestExoPlayerBuilder {
|
||||
.setUseLazyPreparation(useLazyPreparation)
|
||||
.setLooper(looper)
|
||||
.setSeekBackIncrementMs(seekBackIncrementMs)
|
||||
.setSeekForwardIncrementMs(seekForwardIncrementMs);
|
||||
.setSeekForwardIncrementMs(seekForwardIncrementMs)
|
||||
.setDeviceVolumeControlEnabled(deviceVolumeControlEnabled);
|
||||
if (mediaSourceFactory != null) {
|
||||
builder.setMediaSourceFactory(mediaSourceFactory);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user